Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 114 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Multicall | 21529539 | 30 days ago | IN | 0 ETH | 0.01285951 | ||||
Multicall | 21529536 | 30 days ago | IN | 0 ETH | 0.08663012 | ||||
Multicall | 21529534 | 30 days ago | IN | 0 ETH | 0.10047066 | ||||
Multicall | 21529532 | 30 days ago | IN | 0 ETH | 0.10186536 | ||||
Multicall | 21529518 | 30 days ago | IN | 0 ETH | 0.0909457 | ||||
Multicall | 21529516 | 30 days ago | IN | 0 ETH | 0.09306009 | ||||
Multicall | 21529514 | 30 days ago | IN | 0 ETH | 0.09409893 | ||||
Multicall | 21529510 | 30 days ago | IN | 0 ETH | 0.09219065 | ||||
Multicall | 21529506 | 30 days ago | IN | 0 ETH | 0.09809746 | ||||
Multicall | 21529504 | 30 days ago | IN | 0 ETH | 0.10033859 | ||||
Multicall | 21529500 | 30 days ago | IN | 0 ETH | 0.10131124 | ||||
Multicall | 21529498 | 30 days ago | IN | 0 ETH | 0.10110243 | ||||
Multicall | 21529495 | 30 days ago | IN | 0 ETH | 0.11898374 | ||||
Multicall | 21529493 | 30 days ago | IN | 0 ETH | 0.10859491 | ||||
Multicall | 21529491 | 30 days ago | IN | 0 ETH | 0.09375148 | ||||
Multicall | 21529490 | 30 days ago | IN | 0 ETH | 0.10795822 | ||||
Multicall | 21529489 | 30 days ago | IN | 0 ETH | 0.09197833 | ||||
Multicall | 21529485 | 30 days ago | IN | 0 ETH | 0.0955242 | ||||
Multicall | 21529483 | 30 days ago | IN | 0 ETH | 0.09283384 | ||||
Multicall | 21529479 | 30 days ago | IN | 0 ETH | 0.09243579 | ||||
Multicall | 21529478 | 30 days ago | IN | 0 ETH | 0.09091415 | ||||
Multicall | 21529476 | 30 days ago | IN | 0 ETH | 0.08931311 | ||||
Multicall | 21529475 | 30 days ago | IN | 0 ETH | 0.0885454 | ||||
Multicall | 21529474 | 30 days ago | IN | 0 ETH | 0.08780912 | ||||
Multicall | 21529472 | 30 days ago | IN | 0 ETH | 0.07630657 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21528981 | 30 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:
BitmapLayers
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 1000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {PixelLayerResolver} from "../PixelLayerResolver.sol"; contract BitmapLayers is PixelLayerResolver {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {PaletteRegistry} from "./PaletteRegistry.sol"; import {PixelLayerRegistry} from "./PixelLayerRegistry.sol"; import {BitmapImage} from "./library/BitmapImage.sol"; import {SVGImage} from "./library/SVGImage.sol"; contract PixelLayerResolver is PaletteRegistry, PixelLayerRegistry { /*╭─────────────────────────────────────────────────────────────╮*/ /*│ CUSTOM ERRORS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ error InvalidLayerIdsLength(); error InvalidColorBitDepth(); /*╭─────────────────────────────────────────────────────────────╮*/ /*│ EXTERNAL │*/ /*╰─────────────────────────────────────────────────────────────╯*/ struct PaletteParam { string name; uint8 bitsPerColor; bytes colorData; } struct LayerAndPixelParam { LayerParam layer; RectRegion regionParam; uint256 bgcolorOrIndex; bytes pixels; } struct LayerAndPixelRefParam { LayerParam layer; RectRegion regionParam; uint256 bgcolorOrIndex; uint256 pixelRefId; } function createPaletteAndLayer( PaletteParam calldata palette, LayerAndPixelParam[] calldata param1, LayerAndPixelRefParam[] calldata param2 ) public returns (uint256 paletteId, uint256[] memory layerIds, uint256[] memory layerWithRefIds) { paletteId = createPalette(palette.name, palette.bitsPerColor, palette.colorData); { uint256 layerCount = param1.length; layerIds = new uint256[](layerCount); for (uint256 i = 0; i < layerCount; ++i) { LayerAndPixelParam calldata param = param1[i]; layerIds[i] = createLayer( param.layer, param.regionParam, param.bgcolorOrIndex, param.pixels, paletteId ); } } { uint256 layerCount = param2.length; layerWithRefIds = new uint256[](layerCount); for (uint256 i = 0; i < layerCount; ++i) { LayerAndPixelRefParam calldata param = param2[i]; layerWithRefIds[i] = createLayer( param.layer, param.regionParam, param.bgcolorOrIndex, param.pixelRefId, paletteId ); } } } function genBMPFromLayers(uint256[] memory layerIds) public view returns (bytes memory bmp) { (uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixelBuffer) = compositeLayers(layerIds); return BitmapImage.generateBMP(bitsPerPixel, width, height, pixelBuffer); } function genSVGFromLayers(uint256[] memory layerIds) public view returns (bytes memory svg) { (uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixelBuffer) = compositeLayers(layerIds); return bytes(SVGImage.generateSVG(bitsPerPixel, width, height, pixelBuffer)); } function compositeLayers(uint256[] memory layerIds) public view returns (uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixelBuffer) { uint256 layerCount = layerIds.length; require(layerCount > 0, InvalidLayerIdsLength()); _sortLayersByZIndex(layerIds); uint256 paletteId; uint256 bitsPerLayerPixel; bytes memory pixelIdx; bytes memory palette; LayerRegionInfo memory region; (bitsPerLayerPixel, region, paletteId, pixelIdx) = _getLayerInner(layerIds[0]); width = region.layerWidth; height = region.layerHeight; (bitsPerPixel, palette) = _getPaletteColors(paletteId); unchecked { pixelBuffer = new bytes(width * height * (bitsPerPixel >> 3)); if (region.xTL == 0 && region.yTL == 0 && region.xBR == width && region.yBR == height) { _compositeLayerWithPalette( pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel ); } else { _compositeLayerBG(pixelBuffer, palette, bitsPerPixel, region); _compositeActiveRegion( pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel, region ); } for (uint256 i = 1; i < layerCount; ++i) { uint256 tmpUint; (bitsPerLayerPixel, region, tmpUint, pixelIdx) = _getLayerInner(layerIds[i]); // Only fetch palette when it changes. if (tmpUint != paletteId) { paletteId = tmpUint; (tmpUint, palette) = _getPaletteColors(paletteId); // The bits depth of new palette must be same with the first one. require(tmpUint == bitsPerPixel, InvalidColorBitDepth()); } if ( region.xTL == 0 && region.yTL == 0 && region.xBR == width && region.yBR == height ) { _compositeLayerWithPalette( pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel ); } else { _compositeLayerBG(pixelBuffer, palette, bitsPerPixel, region); _compositeActiveRegion( pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel, region ); } } } } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ INTERNAL HELPERS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ function _compositeLayerWithPalette( bytes memory pixelBuffer, bytes memory palette, bytes memory pixelIndex, uint256 bitsPerColor, uint256 bitsPerPixel ) internal pure { unchecked { uint256 pixelCount; uint256 colorMask; uint256 pixelIndexMask; assembly ("memory-safe") { pixelCount := div(mload(pixelBuffer), shr(3, bitsPerColor)) pixelIndexMask := sub(shl(bitsPerPixel, 1), 1) colorMask := sub(shl(bitsPerColor, 1), 1) } for (uint256 i = 0; i < pixelCount; ++i) { // Temporary variable to store internal values, used to avoid 'stack too deep' errors. uint256 tmpUint; uint256 fgColor; assembly { // The start bit of the `i`th index in the `pixelIndex` let elemStartBit := mul(i, bitsPerPixel) // shr(3, idxStartBit) => idxStartBit / 8, it is byte pos let data := mload(add(add(pixelIndex, 0x20), shr(3, elemStartBit))) // and(idxStartBit, 7) => idxStartBit % 8, it is bit offset data := shr(sub(256, add(bitsPerPixel, and(elemStartBit, 7))), data) // Read fg color from palette with `color index` decoded from pixelIndex. // The start bit of the color in the `palette`. elemStartBit := mul(and(data, pixelIndexMask), bitsPerColor) data := mload(add(add(palette, 0x20), shr(3, elemStartBit))) data := shr(sub(256, add(bitsPerColor, and(elemStartBit, 7))), data) fgColor := and(data, colorMask) } uint256 alpha = fgColor & 0xFF; // Fully transparent, keep bgColor if (alpha == 0) continue; // Prepare bgColor offset and the word of current bgColor uint256 bgColorOffset; uint256 bgColorWordShiftCount; assembly { // tmpUint store the `bufStartBit` which is the offset of the color in the pixelBuffer. tmpUint := mul(i, bitsPerColor) bgColorWordShiftCount := sub(256, add(bitsPerColor, and(tmpUint, 7))) bgColorOffset := add(add(pixelBuffer, 0x20), shr(3, tmpUint)) // tmpUint store the whold word. tmpUint := mload(bgColorOffset) } // Blend BGRA if (alpha < 255) { // Read bgColor and blend BGRA, then update new color to fgColor uint256 bgColor; assembly { bgColor := and(shr(bgColorWordShiftCount, tmpUint), colorMask) } fgColor = _blendBGRA(fgColor, bgColor, alpha); } // 1. No transparency, override with fgColor // 2. alpha < 255, override with blended fgColor assembly { let mask := shl(bgColorWordShiftCount, colorMask) let shifted := shl(bgColorWordShiftCount, fgColor) let current := and(tmpUint, not(mask)) mstore(bgColorOffset, or(current, shifted)) } } } } function _compositeActiveRegion( bytes memory pixelBuffer, bytes memory palette, bytes memory pixelIndex, uint256 bitsPerColor, uint256 bitsPerPixel, LayerRegionInfo memory region ) internal pure { unchecked { uint256 colorMask; uint256 pixelIndexMask; assembly ("memory-safe") { pixelIndexMask := sub(shl(bitsPerPixel, 1), 1) colorMask := sub(shl(bitsPerColor, 1), 1) // ! Use `0x00` to store the `pixelIndexPos`. mstore(0x00, 0) } while (region.yTL < region.yBR) { uint256 rowStart = region.yTL * region.layerWidth + region.xTL; uint256 rowEnd = rowStart + region.regionWidth; while (rowStart < rowEnd) { uint256 fgColor; assembly { // The start bit of the `pixelIndexPos`th index in the `pixelIndex` let elemStartBit := mul(mload(0x00), bitsPerPixel) // shr(3, idxStartBit) => idxStartBit / 8, it is byte pos let data := mload(add(add(pixelIndex, 0x20), shr(3, elemStartBit))) // and(idxStartBit, 7) => idxStartBit % 8, it is bit offset data := shr(sub(256, add(bitsPerPixel, and(elemStartBit, 7))), data) // Read fg color from palette with `color index` decoded from pixelIndex. // The start bit of the color in the `palette`. elemStartBit := mul(and(data, pixelIndexMask), bitsPerColor) data := mload(add(add(palette, 0x20), shr(3, elemStartBit))) data := shr(sub(256, add(bitsPerColor, and(elemStartBit, 7))), data) fgColor := and(data, colorMask) } // Fully transparent, keep bgColor if ((fgColor & 0xFF) == 0) { assembly { mstore(0x00, add(mload(0x00), 1)) // ++pixelIndexPos rowStart := add(rowStart, 1) // ++rowStart } continue; } uint256 bgShift; uint256 bgOffset; assembly { let bufStartBit := mul(rowStart, bitsPerColor) bgShift := sub(256, add(bitsPerColor, and(bufStartBit, 7))) bgOffset := add(add(pixelBuffer, 0x20), shr(3, bufStartBit)) } // Blend BGRA if ((fgColor & 0xFF) < 255) { // Read bgColor and blend BGRA, then update new color to fgColor uint256 bgColor; assembly { bgColor := and(shr(bgShift, mload(bgOffset)), colorMask) } fgColor = _blendBGRA(fgColor, bgColor, fgColor & 0xFF); } // 1. No transparency, override with fgColor // 2. alpha < 255, override with blended fgColor assembly { let mask := shl(bgShift, colorMask) let current := and(mload(bgOffset), not(mask)) mstore(bgOffset, or(current, shl(bgShift, fgColor))) } assembly { mstore(0x00, add(mload(0x00), 1)) // ++pixelIndexPos rowStart := add(rowStart, 1) // ++rowStart } } ++region.yTL; } } } function _compositeLayerBG( bytes memory pixelBuffer, bytes memory palette, uint256 bitsPerColor, LayerRegionInfo memory region ) internal pure { uint256 layerBgColor = region.inactiveBgColor; assembly { // Read fg color from palette with `color index` decoded from pixelIndex. // The start bit of the color in the `palette`. let elemStartBit := mul(layerBgColor, bitsPerColor) let data := mload(add(add(palette, 0x20), shr(3, elemStartBit))) data := shr(sub(256, add(bitsPerColor, and(elemStartBit, 7))), data) layerBgColor := and(data, sub(shl(bitsPerColor, 1), 1)) } if (region.yTL > 0) { _compositeLayerRectBG( pixelBuffer, layerBgColor, bitsPerColor, LayerRegionInfo({ xTL: 0, yTL: 0, xBR: region.layerWidth, yBR: region.yTL, regionWidth: region.layerWidth, layerWidth: region.layerWidth, layerHeight: 0, inactiveBgColor: 0 }) ); } if (region.yBR < region.layerHeight) { _compositeLayerRectBG( pixelBuffer, layerBgColor, bitsPerColor, LayerRegionInfo({ xTL: 0, yTL: region.yBR, xBR: region.layerWidth, yBR: region.layerHeight, regionWidth: region.layerWidth, layerWidth: region.layerWidth, layerHeight: 0, inactiveBgColor: 0 }) ); } if (region.xTL > 0) { _compositeLayerRectBG( pixelBuffer, layerBgColor, bitsPerColor, LayerRegionInfo({ xTL: 0, yTL: region.yTL, xBR: region.xTL, yBR: region.yBR, regionWidth: region.xTL, layerWidth: region.layerWidth, layerHeight: 0, inactiveBgColor: 0 }) ); } if (region.xBR < region.layerWidth) { _compositeLayerRectBG( pixelBuffer, layerBgColor, bitsPerColor, LayerRegionInfo({ xTL: region.xBR, yTL: region.yTL, xBR: region.layerWidth, yBR: region.yBR, regionWidth: region.layerWidth - region.xBR, layerWidth: region.layerWidth, layerHeight: 0, inactiveBgColor: 0 }) ); } } function _compositeLayerRectBG( bytes memory pixelBuffer, uint256 layerBgColor, uint256 bitsPerColor, LayerRegionInfo memory region ) internal pure { unchecked { uint256 colorMask = (1 << bitsPerColor) - 1; uint256 alpha = layerBgColor & 0xFF; if (alpha == 0) return; for (uint256 y = region.yTL; y < region.yBR; ++y) { uint256 rowStart = y * region.layerWidth + region.xTL; uint256 rowEnd = rowStart + region.regionWidth; if (alpha == 255) { while (rowStart < rowEnd) { assembly { let bufStartBit := mul(rowStart, bitsPerColor) let shift := sub(256, add(bitsPerColor, and(bufStartBit, 7))) let targetOffset := add(add(pixelBuffer, 0x20), shr(3, bufStartBit)) let mask := shl(shift, colorMask) let current := and(mload(targetOffset), not(mask)) mstore(targetOffset, or(current, shl(shift, layerBgColor))) } ++rowStart; } } else { while (rowStart < rowEnd) { uint256 bgShift; uint256 bgOffset; uint256 bgWord; assembly { let bufStartBit := mul(rowStart, bitsPerColor) bgShift := sub(256, add(bitsPerColor, and(bufStartBit, 7))) bgOffset := add(add(pixelBuffer, 0x20), shr(3, bufStartBit)) bgWord := mload(bgOffset) } uint256 newColor = _blendBGRA(layerBgColor, (bgWord >> bgShift) & colorMask, alpha); assembly { let mask := shl(bgShift, colorMask) let current := and(bgWord, not(mask)) mstore(bgOffset, or(current, shl(bgShift, newColor))) } ++rowStart; } } } } } function _blendBGRA(uint256 fgColor, uint256 bgColor, uint256 fgAlpha) internal pure returns (uint256) { assembly ("memory-safe") { let w2 := sub(255, fgAlpha) // Approximate blended values for B, G, R channels using right shift for division by 255 let b := shr( 8, add(mul(and(shr(24, fgColor), 0xff), fgAlpha), mul(and(shr(24, bgColor), 0xff), w2)) ) let g := shr( 8, add(mul(and(shr(16, fgColor), 0xff), fgAlpha), mul(and(shr(16, bgColor), 0xff), w2)) ) let r := shr( 8, add(mul(and(shr(8, fgColor), 0xff), fgAlpha), mul(and(shr(8, bgColor), 0xff), w2)) ) // Update the new fgColor fgColor := or(or(or(shl(24, b), shl(16, g)), shl(8, r)), fgAlpha) } return fgColor; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {Multicallable} from "solady/utils/Multicallable.sol"; contract PaletteRegistry is Multicallable { using SafeCast for uint256; /*╭─────────────────────────────────────────────────────────────╮*/ /*│ EVENTS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ event PaletteCreated( uint256 indexed paletteId, string name, uint256 bitsPerColor, uint256 totalColors, uint256 colorDataSize, address creator ); /*╭─────────────────────────────────────────────────────────────╮*/ /*│ CUSTOM ERRORS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ error InvalidColorBits(); error InvalidColorDataLength(); /*╭─────────────────────────────────────────────────────────────╮*/ /*│ CONSTANTS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ uint256 public constant BITS_PER_COLOR = 32; /*╭─────────────────────────────────────────────────────────────╮*/ /*│ STORAGE │*/ /*╰─────────────────────────────────────────────────────────────╯*/ struct Palette { uint8 bitsPerColor; uint32 totalColors; string name; bytes colors; } struct PaletteStorage { uint32 lastPaletteId; mapping(uint32 paletteId => Palette palette) palettes; } /// @dev Returns a storage pointer for this contract. function _getPaletteStorage() internal pure virtual returns (PaletteStorage storage $) { /// @solidity memory-safe-assembly assembly { // `keccak256(abi.encode(uint256(keccak256("bmp.storage.PaletteRegistry")) - 1)) & ~bytes32(uint256(0xff))` $.slot := 0x3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca772633200 } } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ EXTERNAL │*/ /*╰─────────────────────────────────────────────────────────────╯*/ /// @param colorData It should be packed in Little-endian with order `BGRA`. function createPalette(string calldata name, uint8 bitsPerColor, bytes calldata colorData) public returns (uint256) { PaletteStorage storage $ = _getPaletteStorage(); uint256 paletteId = ++$.lastPaletteId; Palette storage palette = $.palettes[uint32(paletteId)]; _setPalette(palette, name, bitsPerColor, colorData); emit PaletteCreated( paletteId, name, bitsPerColor, (colorData.length / (bitsPerColor >> 3)), colorData.length, msg.sender ); return paletteId; } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ VIEW │*/ /*╰─────────────────────────────────────────────────────────────╯*/ function getPalettes(uint256[] calldata paletteIds) public view returns (Palette[] memory palettes) { uint256 length = paletteIds.length; palettes = new Palette[](length); mapping(uint32 => Palette) storage _palettes = _getPaletteStorage().palettes; for (uint256 i = 0; i < length; ++i) { palettes[i] = _palettes[uint32(paletteIds[i])]; } } function getPalette(uint256 paletteId) public view returns (Palette memory) { return _getPaletteStorage().palettes[uint32(paletteId)]; } function lastPaletteId() public view returns (uint256) { return _getPaletteStorage().lastPaletteId; } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ INTERNAL HELPERS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ function _setPalette( Palette storage palette, string calldata name, uint8 bitsPerColor, bytes calldata colorData ) internal { require(bitsPerColor == BITS_PER_COLOR, InvalidColorBits()); uint256 perColorBytesLen = bitsPerColor >> 3; uint256 colorDataLength = colorData.length; require( colorDataLength > 0 && colorDataLength % perColorBytesLen == 0, InvalidColorDataLength() ); if (bytes(name).length > 0) palette.name = name; palette.bitsPerColor = bitsPerColor; palette.totalColors = (colorDataLength / perColorBytesLen).toUint32(); palette.colors = colorData; } function _getPaletteColors(uint256 paletteId) internal view returns (uint8 bitsPerColor, bytes memory paletteColors) { Palette storage palette = _getPaletteStorage().palettes[paletteId.toUint32()]; bitsPerColor = palette.bitsPerColor; paletteColors = palette.colors; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {Multicallable} from "solady/utils/Multicallable.sol"; contract PixelLayerRegistry is Multicallable { using SafeCast for uint256; /*╭─────────────────────────────────────────────────────────────╮*/ /*│ EVENTS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ event PixelLayerCreated( uint256 indexed layerId, string name, uint256 zIndex, uint256 bitsPerPixel, uint256 width, uint256 height, RectRegion activeRegion, uint256 regionPixelRefId, uint256 bgColor, uint256 paletteId, address creator ); event PixelDataCreated(uint256 indexed pixelRefId, uint256 pixelDataLength, bytes32 pixelHash); /*╭─────────────────────────────────────────────────────────────╮*/ /*│ CUSTOM ERRORS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ error InvalidPaletteId(); error InvalidPixelBits(); error PixelLayerNotExists(); error InvalidPixelSize(); error InvalidLayerInactiveBgColor(); error InvalidLayerActiveRegionConfig(); /*╭─────────────────────────────────────────────────────────────╮*/ /*│ CONSTANTS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ uint32 public constant EMPTY_PIXEL_LAYER_ID = 0x0; uint256 public constant MAX_BITS_PER_PIXEL = 32; /*╭─────────────────────────────────────────────────────────────╮*/ /*│ STORAGE │*/ /*╰─────────────────────────────────────────────────────────────╯*/ struct PixelData { bytes data; } struct Layer { uint8 zIndex; uint8 bitsPerPixel; uint16 width; uint16 height; /// @dev x Top Left of active region uint16 xTL; /// @dev y Top Left of active region uint16 yTL; /// @dev x Bottom Right of active region uint16 xBR; /// @dev y Bottom Right of active region uint16 yBR; uint32 pixelRefId; /// @dev inactive region bg color or color index when the layer is defined with an active region. uint32 bgColor; uint32 paletteId; string name; } struct PixelLayerStorage { uint32 lastLayerId; uint32 lastPixelRefId; mapping(uint32 layerId => Layer layer) layers; mapping(uint32 pixelRefId => PixelData pixelData) pixelDatas; } /// @dev Returns a storage pointer for this contract. function _getLayerStorage() internal pure virtual returns (PixelLayerStorage storage $) { /// @solidity memory-safe-assembly assembly { // `keccak256(abi.encode(uint256(keccak256("bmp.storage.PixelLayerStorage")) - 1)) & ~bytes32(uint256(0xff))` $.slot := 0x48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d400 } } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ EXTERNAL │*/ /*╰─────────────────────────────────────────────────────────────╯*/ struct RectRegion { uint256 xTL; uint256 yTL; uint256 xBR; uint256 yBR; } struct LayerParam { string name; uint256 zIndex; uint256 bitsPerPixel; uint256 width; uint256 height; } function createLayer(LayerParam calldata layerParam, bytes calldata pixels, uint256 paletteId) public returns (uint256) { return createLayer( layerParam, RectRegion(0, 0, layerParam.width, layerParam.height), 0, pixels, paletteId ); } function createLayer( LayerParam calldata layerParam, RectRegion memory regionParam, uint256 bgcolorOrIndex, bytes calldata pixels, uint256 paletteId ) public returns (uint256) { _checkLayerRegion( regionParam, bgcolorOrIndex, layerParam.width, layerParam.height, layerParam.bitsPerPixel ); _checkLayerData( layerParam.bitsPerPixel, regionParam.xBR - regionParam.xTL, regionParam.yBR - regionParam.yTL, pixels.length ); require(paletteId > 0, InvalidPaletteId()); PixelLayerStorage storage $ = _getLayerStorage(); uint256 pixelRefId = _createPixelData($, pixels); return _createLayer(layerParam, regionParam, bgcolorOrIndex, pixelRefId, paletteId); } function createLayer(LayerParam calldata layerParam, uint256 pixelRefId, uint256 paletteId) public returns (uint256) { return createLayer( layerParam, RectRegion(0, 0, layerParam.width, layerParam.height), 0, pixelRefId, paletteId ); } function createLayer( LayerParam calldata layerParam, RectRegion memory regionParam, uint256 bgcolorOrIndex, uint256 pixelRefId, uint256 paletteId ) public returns (uint256) { _checkLayerRegion( regionParam, bgcolorOrIndex, layerParam.width, layerParam.height, layerParam.bitsPerPixel ); _checkLayerData( layerParam.bitsPerPixel, regionParam.xBR - regionParam.xTL, regionParam.yBR - regionParam.yTL, _getPixelDataRef(_getLayerStorage(), pixelRefId.toUint32()).length ); require(paletteId > 0, InvalidPaletteId()); return _createLayer(layerParam, regionParam, bgcolorOrIndex, pixelRefId, paletteId); } function createPixelData(bytes calldata pixels) public returns (uint256 pixelRefId) { require(pixels.length > 0, InvalidPixelSize()); return _createPixelData(_getLayerStorage(), pixels); } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ VIEW │*/ /*╰─────────────────────────────────────────────────────────────╯*/ function sortLayersByZIndex(uint256[] memory layerIds) public view returns (uint256[] memory) { _sortLayersByZIndex(layerIds); return layerIds; } function getLayers(uint256[] calldata layerIds) public view returns (Layer[] memory layers) { uint256 length = layerIds.length; layers = new Layer[](length); mapping(uint32 => Layer) storage _layers = _getLayerStorage().layers; for (uint256 i = 0; i < length; ++i) { layers[i] = _layers[uint32(layerIds[i])]; } } function getLayer(uint256 layerId) public view returns (Layer memory layer) { return _getLayerStorage().layers[uint32(layerId)]; } function getPixelData(uint256 pixelRefId) public view returns (bytes memory) { return _getPixelDataRef(_getLayerStorage(), pixelRefId.toUint32()); } function lastLayerId() public view returns (uint256) { return _getLayerStorage().lastLayerId; } /*╭─────────────────────────────────────────────────────────────╮*/ /*│ INTERNAL HELPERS │*/ /*╰─────────────────────────────────────────────────────────────╯*/ function _sortLayersByZIndex(uint256[] memory layerIds) internal view { mapping(uint32 => Layer) storage layers = _getLayerStorage().layers; unchecked { uint256 layerCount = _loadMemoryArray(layerIds, 0); if (layerCount > type(uint32).max) { revert SafeCast.SafeCastOverflowedUintDowncast(32, layerCount); } layerCount = layerIds.length; for (uint256 i = 1; i < layerCount; ++i) { uint32 key = _loadMemoryArray(layerIds, i).toUint32(); require(layers[key].bitsPerPixel > 0, PixelLayerNotExists()); uint256 keyZIndex = layers[key].zIndex; uint256 j = i; while ( j > 0 && layers[uint32(_loadMemoryArray(layerIds, j - 1))].zIndex > keyZIndex ) { _storeMemoryArray(layerIds, j, _loadMemoryArray(layerIds, j - 1)); --j; } _storeMemoryArray(layerIds, j, key); } } } function _createLayer( LayerParam calldata layerParam, RectRegion memory regionParam, uint256 bgcolorOrIndex, uint256 pixelRefId, uint256 paletteId ) internal returns (uint256 layerId) { { PixelLayerStorage storage $ = _getLayerStorage(); layerId = ++$.lastLayerId; Layer storage layer = $.layers[uint32(layerId)]; if (bytes(layerParam.name).length > 0) { layer.name = layerParam.name; } layer.zIndex = layerParam.zIndex.toUint8(); layer.bitsPerPixel = layerParam.bitsPerPixel.toUint8(); layer.width = layerParam.width.toUint16(); layer.height = layerParam.height.toUint16(); layer.xTL = regionParam.xTL.toUint16(); layer.yTL = regionParam.yTL.toUint16(); layer.xBR = regionParam.xBR.toUint16(); layer.yBR = regionParam.yBR.toUint16(); layer.bgColor = bgcolorOrIndex.toUint32(); layer.paletteId = paletteId.toUint32(); layer.pixelRefId = pixelRefId.toUint32(); } emit PixelLayerCreated( layerId, layerParam.name, layerParam.zIndex, layerParam.bitsPerPixel, layerParam.width, layerParam.height, regionParam, pixelRefId, bgcolorOrIndex, paletteId, msg.sender ); } function _createPixelData(PixelLayerStorage storage $, bytes calldata pixels) internal returns (uint256 pixelRefId) { pixelRefId = ++$.lastPixelRefId; $.pixelDatas[uint32(pixelRefId)].data = pixels; emit PixelDataCreated(pixelRefId, pixels.length, keccak256(pixels)); } function _getPixelDataRef(PixelLayerStorage storage $, uint32 pixelRefId) internal view returns (bytes storage pixelData) { return $.pixelDatas[pixelRefId].data; } function _checkLayerData( uint256 bitsPerPixel, uint256 width, uint256 height, uint256 pixelBytes ) internal pure { require( 0 < bitsPerPixel && bitsPerPixel <= MAX_BITS_PER_PIXEL && _isValidBitsPerPixel(bitsPerPixel), InvalidPixelBits() ); uint256 totalBits = width * height * bitsPerPixel; uint256 expectedBytes = (totalBits + 7) >> 3; require(pixelBytes == expectedBytes, InvalidPixelSize()); } function _checkLayerRegion( RectRegion memory param, uint256 bgColorOrIndex, uint256 layerWidth, uint256 layerHeight, uint256 bitsPerPixel ) internal pure { require( param.xTL <= param.xBR && param.xBR <= layerWidth && param.yTL <= param.yBR && param.yBR <= layerHeight, InvalidLayerActiveRegionConfig() ); require(bgColorOrIndex <= ((1 << bitsPerPixel) - 1), InvalidLayerInactiveBgColor()); } function _isValidBitsPerPixel(uint256 bitsPerPixel) internal pure returns (bool isValid) { assembly ("memory-safe") { // Create bit mask for valid bits // 0x101010116 = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8) | (1 << 16) | (1 << 24) | (1 << 32) let validMask := 0x101010116 // Right shift validMask by bitsPerPixel and check least significant bit isValid := and(shr(bitsPerPixel, validMask), 1) } } struct LayerRegionInfo { uint256 xTL; uint256 yTL; uint256 xBR; uint256 yBR; uint256 inactiveBgColor; uint256 regionWidth; // xBR - xTL uint256 layerWidth; uint256 layerHeight; } function _getLayerInner(uint256 layerId) internal view returns ( uint256 bitsPerPixel, LayerRegionInfo memory region, uint256 paletteId, bytes memory pixels ) { PixelLayerStorage storage $ = _getLayerStorage(); Layer storage l = $.layers[uint32(layerId)]; bitsPerPixel = l.bitsPerPixel; region.layerWidth = l.width; region.layerHeight = l.height; region.xTL = l.xTL; region.yTL = l.yTL; region.xBR = l.xBR; region.yBR = l.yBR; region.inactiveBgColor = l.bgColor; region.regionWidth = region.xBR - region.xTL; paletteId = l.paletteId; pixels = _getPixelDataRef($, l.pixelRefId); } function _loadMemoryArray(uint256[] memory arr, uint256 index) internal pure returns (uint256 val) { assembly { val := mload(add(add(arr, 0x20), shl(5, index))) } } function _storeMemoryArray(uint256[] memory arr, uint256 index, uint256 val) internal pure { assembly { mstore(add(add(arr, 0x20), shl(5, index)), val) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; library BitmapImage { /// @dev BMP File Header. uint256 private constant BMP_FILE_HEADER_BYTE_SIZE = 14; /// @dev BMP V5 DIB Header. uint256 private constant BMP_V5_HEADER_BYTE_SIZE = 124; function generateBMP(uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixels) internal pure returns (bytes memory bmpData) { bool isRGB = bitsPerPixel <= 24; uint256 imageSize = _bmpImageSize(bitsPerPixel, width, height); uint256 headerSize = BMP_FILE_HEADER_BYTE_SIZE + BMP_V5_HEADER_BYTE_SIZE; bmpData = new bytes(headerSize + imageSize); _writeBMPFileHeader(bmpData, bmpData.length, headerSize); _writeCommonDIBHeader( bmpData, BMP_V5_HEADER_BYTE_SIZE, imageSize, isRGB ? 0 : 3, 0, width, height, bitsPerPixel ); _writeExtraDIBHeader(bmpData); _writePixelData(bmpData, pixels, headerSize, width, height, bitsPerPixel >> 3); return bmpData; } function _bmpImageSize(uint256 bitsPerPixel, uint256 width, uint256 height) private pure returns (uint256) { unchecked { uint256 bytesPerPixel = bitsPerPixel >> 3; uint256 rowSize = width * bytesPerPixel; return (rowSize + ((4 - (rowSize & 3)) & 3)) * height; } } function _writeBMPFileHeader(bytes memory bmpData, uint256 fileSize, uint256 pixelOffset) private pure { // Write BMP header (14 bytes) assembly { let ptr := add(bmpData, 32) mstore8(ptr, 0x42) // B mstore8(add(ptr, 1), 0x4D) // M } _writeUint32(bmpData, 2, fileSize); _writeUint32(bmpData, 10, pixelOffset); // offset to pixel data } function _writeCommonDIBHeader( bytes memory bmpData, uint256 dibHeaderSize, uint256 imageSize, uint256 compressionOption, uint256 paletteColorCount, uint256 width, uint256 height, uint256 bitsPerPixel ) private pure { // Write BITMAPV4HEADER (108 bytes) _writeUint32(bmpData, 14, dibHeaderSize); // BITMAPV4HEADER size _writeUint32(bmpData, 18, width); _writeUint32(bmpData, 22, height); _writeUint16(bmpData, 26, 1); // planes must always be 1 _writeUint16(bmpData, 28, bitsPerPixel); // bits per pixel _writeUint32(bmpData, 30, compressionOption); // compression; 0 - BI_RGB, 3 - BI_BITFIELDS _writeUint32(bmpData, 34, imageSize); // _writeUint32(bmpData, 38, 0); // x pixel per meter // _writeUint32(bmpData, 42, 0); // y pixel per meter _writeUint32(bmpData, 46, paletteColorCount); // color count // _writeUint32(bmpData, 50, 0); // important color count } function _writeExtraDIBHeader(bytes memory bmpData) private pure { // BITMAPV5HEADER additional fields _writeUint32(bmpData, 54, 0x00FF0000); // Red mask _writeUint32(bmpData, 58, 0x0000FF00); // Green mask _writeUint32(bmpData, 62, 0x000000FF); // Blue mask _writeUint32(bmpData, 66, 0xFF000000); // Alpha mask _writeUint32(bmpData, 70, 0x73524742); // Color space type (sRGB) } function _writePixelData( bytes memory bmpData, bytes memory pixelBuffer, uint256 pixelOffset, uint256 width, uint256 height, uint256 bytesPerPixel ) private pure { assembly { let bytesPerRow := mul(width, bytesPerPixel) let paddedBytesPerRow := add(bytesPerRow, and(sub(4, and(bytesPerRow, 3)), 3)) let bmpDataPtr := add(add(bmpData, 0x20), pixelOffset) let pixelBufferPtr := add(pixelBuffer, 0x20) let heightMinus1 := sub(height, 1) for { let y := 0 } lt(y, height) { y := add(y, 1) } { mcopy( add(bmpDataPtr, mul(sub(heightMinus1, y), paddedBytesPerRow)), add(pixelBufferPtr, mul(y, bytesPerRow)), bytesPerRow ) } } } // Helper function to write uint32 to byte array in Little-endian function _writeUint32(bytes memory data, uint256 offset, uint256 value) private pure { assembly { let ptr := add(add(data, 32), offset) mstore8(ptr, value) mstore8(add(ptr, 1), shr(8, value)) mstore8(add(ptr, 2), shr(16, value)) mstore8(add(ptr, 3), shr(24, value)) } } // Helper function to write uint16 to byte array in Little-endian function _writeUint16(bytes memory data, uint256 offset, uint256 value) private pure { assembly { let ptr := add(add(data, 32), offset) mstore8(ptr, value) mstore8(add(ptr, 1), shr(8, value)) } } // Helper function to write bytes to byte array function _writeBytes(bytes memory data, uint256 offset, bytes memory value) private pure { assembly { mcopy(add(add(data, 32), offset), add(value, 32), mload(value)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; library SVGImage { function generateSVG(uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixels) internal pure returns (string memory svg) { uint256 ptr; assembly { svg := mload(0x40) ptr := add(svg, 0x20) // Store "0123456789abcdef" in scratch space. Used to covert hex string. mstore(0x0f, 0x30313233343536373839616263646566) } ptr = _writeSVGHeader(ptr, width, height); unchecked { uint256 colorMask = (1 << bitsPerPixel) - 1; for (uint256 y = 0; y < height; ++y) { uint256 startX; uint256 currentColor = type(uint256).max; uint256 basePixelOffset = y * width; for (uint256 x = 0; x < width; ++x) { uint256 color = _getPixel(pixels, colorMask, bitsPerPixel, basePixelOffset + x); // Skip transparent pixels if (uint8(color) == 0) { if (currentColor < type(uint256).max) { // Add path for previous segment ptr = _writePath(ptr, startX, y, x - startX, currentColor); currentColor = type(uint256).max; } startX = x + 1; continue; } if (currentColor == type(uint256).max) { currentColor = color; startX = x; } else if (color != currentColor) { // Color changed, add path for previous segment ptr = _writePath(ptr, startX, y, x - startX, currentColor); currentColor = color; startX = x; } } // Add remaining segment at end of row if (currentColor < type(uint256).max && startX < width) { ptr = _writePath(ptr, startX, y, width - startX, currentColor); } } } assembly { // '</svg>' mstore(ptr, 0x3c2f7376673e0000000000000000000000000000000000000000000000000000) ptr := add(ptr, 6) let length := sub(ptr, add(svg, 0x20)) mstore(svg, length) let padding := and(sub(32, and(ptr, 31)), 31) mstore(0x40, add(ptr, padding)) } } function _writeSVGHeader(uint256 ptr, uint256 width, uint256 height) private pure returns (uint256) { assembly { // '<svg shape-rendering="crispEdges" width="' (32 + 9 bytes) mstore(ptr, 0x3c7376672073686170652d72656e646572696e673d2263726973704564676573) ptr := add(ptr, 32) mstore(ptr, 0x222077696474683d220000000000000000000000000000000000000000000000) ptr := add(ptr, 9) } ptr = _writeUint(ptr, width); assembly { // '" height="' (10 bytes) mstore(ptr, 0x22206865696768743d2200000000000000000000000000000000000000000000) ptr := add(ptr, 10) } ptr = _writeUint(ptr, height); assembly { // '" viewBox="0 0 ' (15 bytes) mstore(ptr, 0x222076696577426f783d22302030200000000000000000000000000000000000) ptr := add(ptr, 15) } ptr = _writeUint(ptr, width); assembly { mstore8(ptr, 0x20) ptr := add(ptr, 1) } ptr = _writeUint(ptr, height); assembly { // '" xmlns="http://www.w3.org/2000/svg">' (33 bytes) mstore(ptr, 0x2220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f) ptr := add(ptr, 32) mstore(ptr, 0x737667223e000000000000000000000000000000000000000000000000000000) ptr := add(ptr, 5) } return ptr; } function _writePath(uint256 ptr, uint256 x, uint256 y, uint256 width, uint256 color) private pure returns (uint256) { assembly { // '<path d="M' (10 bytes) mstore(ptr, 0x3c7061746820643d224d00000000000000000000000000000000000000000000) ptr := add(ptr, 10) } ptr = _writeUint(ptr, x); assembly { mstore8(ptr, 0x20) ptr := add(ptr, 1) } ptr = _writeUint(ptr, y); assembly { // 'v1h' (3 bytes) mstore(ptr, 0x7631680000000000000000000000000000000000000000000000000000000000) ptr := add(ptr, 3) } ptr = _writeUint(ptr, width); assembly { // 'v-1" fill="#' (12 bytes) mstore(ptr, 0x762d31222066696c6c3d22230000000000000000000000000000000000000000) ptr := add(ptr, 12) } { uint256 b = uint8(color >> 24); uint256 g = uint8(color >> 16); uint256 r = uint8(color >> 8); uint256 a = uint8(color); ptr = _writeUintHex(ptr, (r << 24) | (g << 16) | (b << 8) | a, 8); } assembly { // '"/>' (3 bytes) mstore(ptr, 0x222f3e0000000000000000000000000000000000000000000000000000000000) ptr := add(ptr, 3) } return ptr; } function _writeUintHex(uint256 ptr, uint256 value, uint256 hexLength) private pure returns (uint256) { assembly { let end := add(ptr, hexLength) let result := end // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { result := sub(result, 2) mstore8(add(result, 1), mload(and(value, 15))) mstore8(result, mload(and(shr(4, value), 15))) value := shr(8, value) if iszero(xor(result, ptr)) { break } } ptr := end } return ptr; } function _writeUint(uint256 ptr, uint256 value) private pure returns (uint256) { assembly { let len := 1 let v := div(value, 10) for {} v {} { len := add(len, 1) v := div(v, 10) } v := add(ptr, len) for { let end := v } 1 {} { end := sub(end, 1) // Store the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(end, add(48, mod(value, 10))) value := div(value, 10) // Keep dividing `value` until zero. if iszero(value) { break } } ptr := v } return ptr; } function _getPixel(bytes memory pixels, uint256 pixelMask, uint256 bitsPerPixel, uint256 index) private pure returns (uint256 result) { assembly ("memory-safe") { let elemStartBit := mul(index, bitsPerPixel) let data := mload(add(add(pixels, 0x20), shr(3, elemStartBit))) data := shr(sub(256, add(bitsPerPixel, and(elemStartBit, 7))), data) result := and(data, pixelMask) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Contract that enables a single call to call multiple methods on itself. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Multicallable.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Multicallable.sol) /// /// WARNING: /// This implementation is NOT to be used with ERC2771 out-of-the-box. /// https://blog.openzeppelin.com/arbitrary-address-spoofing-vulnerability-erc2771context-multicall-public-disclosure /// This also applies to potentially other ERCs / patterns appending to the back of calldata. /// /// We do NOT have a check for ERC2771, as we do not inherit from OpenZeppelin's context. /// Moreover, it is infeasible and inefficient for us to add checks and mitigations /// for all possible ERC / patterns appending to the back of calldata. /// /// We would highly recommend using an alternative pattern such as /// https://github.com/Vectorized/multicaller /// which is more flexible, futureproof, and safer by default. abstract contract Multicallable { /// @dev Apply `delegatecall` with the current contract to each calldata in `data`, /// and store the `abi.encode` formatted results of each `delegatecall` into `results`. /// If any of the `delegatecall`s reverts, the entire context is reverted, /// and the error is bubbled up. /// /// By default, this function directly returns the results and terminates the call context. /// If you need to add before and after actions to the multicall, please override this function. function multicall(bytes[] calldata data) public payable virtual returns (bytes[] memory) { // Revert if `msg.value` is non-zero by default to guard against double-spending. // (See: https://www.paradigm.xyz/2021/08/two-rights-might-make-a-wrong) // // If you really need to pass in a `msg.value`, then you will have to // override this function and add in any relevant before and after checks. if (msg.value != 0) revert(); // `_multicallDirectReturn` returns the results directly and terminates the call context. _multicallDirectReturn(_multicall(data)); } /// @dev The inner logic of `multicall`. /// This function is included so that you can override `multicall` /// to add before and after actions, and use the `_multicallDirectReturn` function. function _multicall(bytes[] calldata data) internal virtual returns (bytes32 results) { /// @solidity memory-safe-assembly assembly { results := mload(0x40) mstore(results, 0x20) mstore(add(0x20, results), data.length) let c := add(0x40, results) let s := c let end := shl(5, data.length) calldatacopy(c, data.offset, end) end := add(c, end) let m := end if data.length { for {} 1 {} { let o := add(data.offset, mload(c)) calldatacopy(m, add(o, 0x20), calldataload(o)) // forgefmt: disable-next-item if iszero(delegatecall(gas(), address(), m, calldataload(o), codesize(), 0x00)) { // Bubble up the revert if the delegatecall reverts. returndatacopy(results, 0x00, returndatasize()) revert(results, returndatasize()) } mstore(c, sub(m, s)) c := add(0x20, c) // Append the `returndatasize()`, and the return data. mstore(m, returndatasize()) let b := add(m, 0x20) returndatacopy(b, 0x00, returndatasize()) // Advance `m` by `returndatasize() + 0x20`, // rounded up to the next multiple of 32. m := and(add(add(b, returndatasize()), 0x1f), 0xffffffffffffffe0) mstore(add(b, returndatasize()), 0) // Zeroize the slot after the returndata. if iszero(lt(c, end)) { break } } } mstore(0x40, m) // Allocate memory. results := or(shl(64, m), results) // Pack the bytes length into `results`. } } /// @dev Decodes the `results` into an array of bytes. /// This can be useful if you need to access the results or re-encode it. function _multicallResultsToBytesArray(bytes32 results) internal pure virtual returns (bytes[] memory decoded) { /// @solidity memory-safe-assembly assembly { decoded := mload(0x40) let c := and(0xffffffffffffffff, results) // Extract the offset. mstore(decoded, mload(add(c, 0x20))) // Store the length. let o := add(decoded, 0x20) // Start of elements in `decoded`. let end := add(o, shl(5, mload(decoded))) mstore(0x40, end) // Allocate memory. let s := add(c, 0x40) // Start of elements in `results`. let d := sub(s, o) // Difference between input and output pointers. for {} iszero(eq(o, end)) { o := add(o, 0x20) } { mstore(o, add(mload(add(d, o)), s)) } } } /// @dev Directly returns the `results` and terminates the current call context. /// `results` must be from `_multicall`, else behavior is undefined. function _multicallDirectReturn(bytes32 results) internal pure virtual { /// @solidity memory-safe-assembly assembly { return(and(0xffffffffffffffff, results), shr(64, results)) } } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "@openzeppelin/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/", "solady/=lib/solady/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"InvalidColorBitDepth","type":"error"},{"inputs":[],"name":"InvalidColorBits","type":"error"},{"inputs":[],"name":"InvalidColorDataLength","type":"error"},{"inputs":[],"name":"InvalidLayerActiveRegionConfig","type":"error"},{"inputs":[],"name":"InvalidLayerIdsLength","type":"error"},{"inputs":[],"name":"InvalidLayerInactiveBgColor","type":"error"},{"inputs":[],"name":"InvalidPaletteId","type":"error"},{"inputs":[],"name":"InvalidPixelBits","type":"error"},{"inputs":[],"name":"InvalidPixelSize","type":"error"},{"inputs":[],"name":"PixelLayerNotExists","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"paletteId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"bitsPerColor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalColors","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"colorDataSize","type":"uint256"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"PaletteCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pixelRefId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pixelDataLength","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"pixelHash","type":"bytes32"}],"name":"PixelDataCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"layerId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"zIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"width","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"height","type":"uint256"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"indexed":false,"internalType":"struct PixelLayerRegistry.RectRegion","name":"activeRegion","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"regionPixelRefId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bgColor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paletteId","type":"uint256"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"PixelLayerCreated","type":"event"},{"inputs":[],"name":"BITS_PER_COLOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMPTY_PIXEL_LAYER_ID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BITS_PER_PIXEL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"compositeLayers","outputs":[{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"},{"internalType":"bytes","name":"pixelBuffer","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"internalType":"bytes","name":"pixels","type":"bytes"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"uint256","name":"pixelRefId","type":"uint256"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"bytes","name":"pixels","type":"bytes"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"internalType":"uint256","name":"pixelRefId","type":"uint256"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"bytes","name":"colorData","type":"bytes"}],"name":"createPalette","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"bytes","name":"colorData","type":"bytes"}],"internalType":"struct PixelLayerResolver.PaletteParam","name":"palette","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layer","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"bytes","name":"pixels","type":"bytes"}],"internalType":"struct PixelLayerResolver.LayerAndPixelParam[]","name":"param1","type":"tuple[]"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layer","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"uint256","name":"pixelRefId","type":"uint256"}],"internalType":"struct PixelLayerResolver.LayerAndPixelRefParam[]","name":"param2","type":"tuple[]"}],"name":"createPaletteAndLayer","outputs":[{"internalType":"uint256","name":"paletteId","type":"uint256"},{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"},{"internalType":"uint256[]","name":"layerWithRefIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"pixels","type":"bytes"}],"name":"createPixelData","outputs":[{"internalType":"uint256","name":"pixelRefId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"genBMPFromLayers","outputs":[{"internalType":"bytes","name":"bmp","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"genSVGFromLayers","outputs":[{"internalType":"bytes","name":"svg","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"layerId","type":"uint256"}],"name":"getLayer","outputs":[{"components":[{"internalType":"uint8","name":"zIndex","type":"uint8"},{"internalType":"uint8","name":"bitsPerPixel","type":"uint8"},{"internalType":"uint16","name":"width","type":"uint16"},{"internalType":"uint16","name":"height","type":"uint16"},{"internalType":"uint16","name":"xTL","type":"uint16"},{"internalType":"uint16","name":"yTL","type":"uint16"},{"internalType":"uint16","name":"xBR","type":"uint16"},{"internalType":"uint16","name":"yBR","type":"uint16"},{"internalType":"uint32","name":"pixelRefId","type":"uint32"},{"internalType":"uint32","name":"bgColor","type":"uint32"},{"internalType":"uint32","name":"paletteId","type":"uint32"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct PixelLayerRegistry.Layer","name":"layer","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"getLayers","outputs":[{"components":[{"internalType":"uint8","name":"zIndex","type":"uint8"},{"internalType":"uint8","name":"bitsPerPixel","type":"uint8"},{"internalType":"uint16","name":"width","type":"uint16"},{"internalType":"uint16","name":"height","type":"uint16"},{"internalType":"uint16","name":"xTL","type":"uint16"},{"internalType":"uint16","name":"yTL","type":"uint16"},{"internalType":"uint16","name":"xBR","type":"uint16"},{"internalType":"uint16","name":"yBR","type":"uint16"},{"internalType":"uint32","name":"pixelRefId","type":"uint32"},{"internalType":"uint32","name":"bgColor","type":"uint32"},{"internalType":"uint32","name":"paletteId","type":"uint32"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct PixelLayerRegistry.Layer[]","name":"layers","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"getPalette","outputs":[{"components":[{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"uint32","name":"totalColors","type":"uint32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"bytes","name":"colors","type":"bytes"}],"internalType":"struct PaletteRegistry.Palette","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"paletteIds","type":"uint256[]"}],"name":"getPalettes","outputs":[{"components":[{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"uint32","name":"totalColors","type":"uint32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"bytes","name":"colors","type":"bytes"}],"internalType":"struct PaletteRegistry.Palette[]","name":"palettes","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pixelRefId","type":"uint256"}],"name":"getPixelData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastLayerId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPaletteId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"sortLayersByZIndex","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052348015600e575f5ffd5b506139df8061001c5f395ff3fe60806040526004361061016d575f3560e01c8063837ab668116100c6578063ac9650d81161007c578063df0c783811610057578063df0c783814610316578063dfdaf5281461040d578063f781e3ae14610439575f5ffd5b8063ac9650d8146103ba578063c278dba3146103da578063ccbe1ed2146103f9575f5ffd5b806394ac753e116100ac57806394ac753e14610368578063a21abed81461037c578063a26327ff1461039b575f5ffd5b8063837ab6681461032a57806390c302e714610349575f5ffd5b8063505e570a1161012657806360ff37bc1161010157806360ff37bc146102cb5780636abf7826146102f75780637b7e260514610316575f5ffd5b8063505e570a1461024b57806351c39604146102775780635840b0f81461029f575f5ffd5b80632cc4dcb6116101565780632cc4dcb6146101cf57806347d02b81146101ee57806349f83b1f1461021c575f5ffd5b80630d499331146101715780631adb75ac146101a3575b5f5ffd5b34801561017c575f5ffd5b5061019061018b366004612d98565b610465565b6040519081526020015b60405180910390f35b3480156101ae575f5ffd5b506101c26101bd366004612e49565b6104a5565b60405161019a9190612fc2565b3480156101da575f5ffd5b506101906101e93660046130cb565b610731565b3480156101f9575f5ffd5b5061020d610208366004613130565b61080a565b60405161019a93929190613208565b348015610227575f5ffd5b5061023b610236366004613232565b6109ea565b60405161019a94939291906132de565b348015610256575f5ffd5b5061026a610265366004613302565b610c72565b60405161019a9190613363565b348015610282575f5ffd5b5061028a5f81565b60405163ffffffff909116815260200161019a565b3480156102aa575f5ffd5b506102be6102b9366004613302565b610e10565b60405161019a9190613375565b3480156102d6575f5ffd5b506102ea6102e5366004613232565b610ecd565b60405161019a9190613387565b348015610302575f5ffd5b506102be610311366004613232565b610edc565b348015610321575f5ffd5b50610190602081565b348015610335575f5ffd5b50610190610344366004613399565b610eff565b348015610354575f5ffd5b50610190610363366004613427565b610fb7565b348015610373575f5ffd5b50610190610ff5565b348015610387575f5ffd5b506102be610396366004613232565b611024565b3480156103a6575f5ffd5b506101906103b5366004613486565b611047565b6103cd6103c8366004612e49565b61111c565b60405161019a91906134f6565b3480156103e5575f5ffd5b506101906103f436600461354d565b611140565b348015610404575f5ffd5b50610190611191565b348015610418575f5ffd5b5061042c610427366004612e49565b6111b8565b60405161019a9190613580565b348015610444575f5ffd5b50610458610453366004613302565b6113f4565b60405161019a91906135d7565b5f61049c8560405180608001604052805f81526020015f81526020018860600135815260200188608001358152505f878787610eff565b95945050505050565b6060818067ffffffffffffffff8111156104c1576104c1613025565b60405190808252806020026020018201604052801561055057816020015b60408051610180810182525f808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e083018290526101008301829052610120830182905261014083019190915261016082015282525f199092019101816104df5790505b5091507f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4015f5b8281101561072857815f878784818110610592576105926135e9565b63ffffffff6020918202939093013583168452838101949094525060409182015f20825161018081018452815460ff80821683526101008083049091169683019690965261ffff6201000082048116958301959095526401000000008104851660608301526601000000000000810485166080830152680100000000000000008104851660a08301526a01000000000000000000008104851660c0830152600160601b810490941660e0820152600160701b8404831694810194909452600160901b83048216610120850152600160b01b9092041661014083015260018101805461016084019190610683906135fd565b80601f01602080910402602001604051908101604052809291908181526020018280546106af906135fd565b80156106fa5780601f106106d1576101008083540402835291602001916106fa565b820191905f5260205f20905b8154815290600101906020018083116106dd57829003601f168201915b505050505081525050848281518110610715576107156135e9565b6020908102919091010152600101610576565b50505092915050565b5f61074b8585886060013589608001358a60400135611566565b6107d38660400135865f015187604001516107669190613643565b8760200151886060015161077a9190613643565b6107c17f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4006107a789611626565b63ffffffff165f9081526002919091016020526040902090565b80546107cc906135fd565b905061165b565b5f82116107f357604051632b4582a560e01b815260040160405180910390fd5b6108008686868686611706565b9695505050505050565b5f60608061083861081b8980613656565b61082b60408c0160208d01613699565b6103b560408d018d613656565b9250858067ffffffffffffffff81111561085457610854613025565b60405190808252806020026020018201604052801561087d578160200160208202803683370190505b5092505f5b8181101561090e573689898381811061089d5761089d6135e9565b90506020028101906108af91906136b2565b90506108e86108be82806136d0565b6108d0368490038401602085016136e4565b60a08401356108e260c0860186613656565b8b610eff565b8583815181106108fa576108fa6135e9565b602090810291909101015250600101610882565b508490508067ffffffffffffffff81111561092b5761092b613025565b604051908082528060200260200182016040528015610954578160200160208202803683370190505b5091505f5b818110156109dd5736878783818110610974576109746135e9565b905060200281019061098691906136b2565b90506109b761099582806136d0565b6109a7368490038401602085016136e4565b8360a001358460c001358a610731565b8483815181106109c9576109c96135e9565b602090810291909101015250600101610959565b5050955095509592505050565b5f5f5f60605f855190505f8111610a2d576040517f21fa0dc700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3686611a29565b5f5f606080610a7b6040518061010001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b610a9d8b5f81518110610a9057610a906135e9565b6020026020010151611bac565b60c083015160e0840151909d509b509097509195509093509050610ac085611d9c565b8160ff169150809350819b50505060038a901c888a020267ffffffffffffffff811115610aef57610aef613025565b6040519080825280601f01601f191660200182016040528015610b19576020820181803683370190505b508151909750158015610b2e57506020810151155b8015610b3d5750888160400151145b8015610b4c5750878160600151145b15610b6357610b5e8783858d88611e7f565b610b7d565b610b6f87838c84611fb1565b610b7d8783858d888661217e565b60015b86811015610c64575f610b9e8d8381518110610a9057610a906135e9565b92985091965093509050868114610bfb57809650610bbb87611d9c565b945060ff1690508b8114610bfb576040517f23f838ec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251158015610c0c57506020830151155b8015610c1b57508a8360400151145b8015610c2a5750898360600151145b15610c4157610c3c8985878f8a611e7f565b610c5b565b610c4d89858e86611fb1565b610c5b8985878f8a8861217e565b50600101610b80565b505050505050509193509193565b60408051608080820183525f808352602080840182905260608486018190528085015263ffffffff86811683527f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca77263320182529185902085519384018652805460ff81168552610100900490921690830152600181018054939492939192840191610cf9906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610d25906135fd565b8015610d705780601f10610d4757610100808354040283529160200191610d70565b820191905f5260205f20905b815481529060010190602001808311610d5357829003601f168201915b50505050508152602001600282018054610d89906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610db5906135fd565b8015610e005780601f10610dd757610100808354040283529160200191610e00565b820191905f5260205f20905b815481529060010190602001808311610de357829003601f168201915b5050505050815250509050919050565b6060610e3f7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4006107a784611626565b8054610e4a906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610e76906135fd565b8015610ec15780601f10610e9857610100808354040283529160200191610ec1565b820191905f5260205f20905b815481529060010190602001808311610ea457829003601f168201915b50505050509050919050565b6060610ed882611a29565b5090565b60605f5f5f5f610eeb866109ea565b9350935093509350610800848484846122fb565b5f610f19868689606001358a608001358b60400135611566565b610f4e8760400135875f01518860400151610f349190613643565b88602001518960600151610f489190613643565b8661165b565b5f8211610f6e57604051632b4582a560e01b815260040160405180910390fd5b7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4005f610f9b8287876123c6565b9050610faa8989898488611706565b9998505050505050505050565b5f610fed8460405180608001604052805f81526020015f81526020018760600135815260200187608001358152505f8686610731565b949350505050565b5f7f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca7726332005b5463ffffffff16919050565b60605f5f5f5f611033866109ea565b93509350935093506108008484848461247f565b7f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca77263320080545f91908290829082906110829063ffffffff166136fe565b825463ffffffff9182166101009390930a83810292021916179091555f81815260018401602052604090209091506110be818a8a8a8a8a6125d9565b817f73b05f94061684c43b9361fa65b5b965397451ddaa3035fce829f4fdc43997168a8a8a6110f4601f600383901c168b613736565b60405161110894939291908c903390613771565b60405180910390a250979650505050505050565b60603415611128575f5ffd5b61113a61113584846126c7565b612753565b92915050565b5f8161115f576040516306e5cf7960e21b815260040160405180910390fd5b61118a7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40084846123c6565b9392505050565b5f7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d400611018565b6060818067ffffffffffffffff8111156111d4576111d4613025565b60405190808252806020026020018201604052801561122757816020015b604080516080810182525f80825260208201526060918101829052818101919091528152602001906001900390816111f25790505b5091507f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca7726332015f5b8281101561072857815f878784818110611269576112696135e9565b63ffffffff6020918202939093013583168452838101949094525060409182015f208251608081018452815460ff811682526101009004909216938201939093526001830180549193928401916112bf906135fd565b80601f01602080910402602001604051908101604052809291908181526020018280546112eb906135fd565b80156113365780601f1061130d57610100808354040283529160200191611336565b820191905f5260205f20905b81548152906001019060200180831161131957829003601f168201915b5050505050815260200160028201805461134f906135fd565b80601f016020809104026020016040519081016040528092919081815260200182805461137b906135fd565b80156113c65780601f1061139d576101008083540402835291602001916113c6565b820191905f5260205f20905b8154815290600101906020018083116113a957829003601f168201915b5050505050815250508482815181106113e1576113e16135e9565b602090810291909101015260010161124d565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201929092526101608101919091527f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40063ffffffff8084165f90815260019283016020908152604091829020825161018081018452815460ff80821683526101008083049091169483019490945261ffff6201000082048116958301959095526401000000008104851660608301526601000000000000810485166080830152680100000000000000008104851660a08301526a01000000000000000000008104851660c0830152600160601b810490941660e0820152600160701b8404851692810192909252600160901b83048416610120830152600160b01b909204909216610140830152918201805491929161016084019190610d89906135fd565b604085015185511180159061157f575082856040015111155b801561159357508460600151856020015111155b80156115a3575081856060015111155b6115d9576040517f45e4a28400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115e6600180831b613643565b84111561161f576040517f24aad79700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b5f63ffffffff821115610ed8576040516306dfcc6560e41b815260206004820152602481018390526044015b60405180910390fd5b835f10801561166b575060208411155b801561167e57506001640101010116851c165b6116b4576040517f10c88af100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f846116c084866137c2565b6116ca91906137c2565b90505f60036116da8360076137d9565b901c90508083146116fe576040516306e5cf7960e21b815260040160405180910390fd5b505050505050565b7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40080545f91908190839061173f9063ffffffff166136fe565b825463ffffffff9182166101009390930a83810292021916179091555f81815260018301602052604081209193506117778980613656565b9050111561179b576117898880613656565b6001830191611799919083613830565b505b6117a88860200135612764565b815460ff191660ff919091161781556117c46040890135612764565b815460ff919091166101000261ff00199091161781556117e76060890135612791565b815461ffff91909116620100000263ffff00001990911617815561180e6080890135612791565b815461ffff919091166401000000000265ffff0000000019909116178155865161183790612791565b815461ffff9190911666010000000000000267ffff00000000000019909116178155602087015161186790612791565b815461ffff91909116680100000000000000000269ffff000000000000000019909116178155604087015161189b90612791565b815461ffff919091166a0100000000000000000000026bffff000000000000000000001990911617815560608701516118d390612791565b815461ffff91909116600160601b026dffff0000000000000000000000001990911617815561190186611626565b815463ffffffff91909116600160901b027fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff90911617815561194284611626565b815463ffffffff91909116600160b01b027fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff90911617815561198385611626565b815463ffffffff91909116600160701b027fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff90911617905550807f354260e53682a8b55f8da011fb4d880b47efb2d44dd4c2502511508e3cd59d276119e88880613656565b89602001358a604001358b606001358c608001358c8b8d8c33604051611a189b9a999897969594939291906138ea565b60405180910390a295945050505050565b60208101517f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4019063ffffffff811115611a7f576040516306dfcc6560e41b81526020600482015260248101829052604401611652565b50815160015b81811015611ba6575f611aa6611aa1868460051b016020015190565b611626565b63ffffffff81165f90815260208690526040902054909150610100900460ff16611afc576040517f2eb8a6de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f9081526020859052604090205460ff16825b5f81118015611b51575081865f611b368a6001860360051b016020015190565b63ffffffff16815260208101919091526040015f205460ff16115b15611b8657611b7e8782611b6e8a6001860360051b016020015190565b808260051b602085010152505050565b5f1901611b16565b63ffffffff8316600582901b880160200152505050806001019050611a85565b50505050565b5f611bed6040518061010001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b63ffffffff8381165f9081527f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40160209081526040808320805461ffff620100008204811660c08901526401000000008204811660e08901526601000000000000820481168089526801000000000000000083048216958901959095526a010000000000000000000082048116938801849052600160601b820416606088810191909152600160901b8204909616608088015260ff6101009091041696509293927f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d400929091611cdb9190613643565b60a0860152805463ffffffff600160701b820481165f9081526002850160205260409020600160b01b9092041694508054611d15906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611d41906135fd565b8015611d8c5780601f10611d6357610100808354040283529160200191611d8c565b820191905f5260205f20905b815481529060010190602001808311611d6f57829003601f168201915b5050505050925050509193509193565b5f6060817f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca77263320181611dcb86611626565b63ffffffff16815260208101919091526040015f20805460028201805460ff9092169550919250611dfb906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611e27906135fd565b8015611e725780601f10611e4957610100808354040283529160200191611e72565b820191905f5260205f20905b815481529060010190602001808311611e5557829003601f168201915b5050505050915050915091565b8451600383901c9004600180841b5f1990810191841b015f5b83811015611fa6576020858202600381811c8a01830151600792831689016101009081039190911c86168a029182901c8c01909301515f9391909216890190031c841660ff8116808303611eee57505050611f9e565b838902600381901c8d0160200180519450906007168a016101000360ff831015611f895784811c8816611f858582865f8160ff038060ff8560181c16028360ff8760181c16020160081c8160ff8660101c16028460ff8860101c16020160081c8260ff8760081c16028560ff8960081c16020160081c9250848360081b8260101b8460181b17171796505050508390509392505050565b9450505b87811b19949094169290931b91909117909152505b600101611e98565b505050505050505050565b60808101516020908302600381901c85018201519183015160079091168401610100039190911c6001841b5f190116901561203b5761203b8582856040518061010001604052805f81526020015f81526020018760c001518152602001876020015181526020015f81526020018760c0015181526020018760c0015181526020015f8152506127bf565b8160e00151826060015110156120a4576120a48582856040518061010001604052805f8152602001876060015181526020018760c0015181526020018760e0015181526020015f81526020018760c0015181526020018760c0015181526020015f8152506127bf565b815115612102576121028582856040518061010001604052805f815260200187602001518152602001875f01518152602001876060015181526020015f8152602001875f015181526020018760c0015181526020015f8152506127bf565b8160c001518260400151101561161f5761161f85828560405180610100016040528087604001518152602001876020015181526020018760c001518152602001876060015181526020015f815260200187604001518860c001516121669190613643565b81526020018760c0015181526020015f8152506127bf565b5f8052600180841b5f1990810191841b015b8260600151836020015110156122f157825160c0840151602085015160a086015191029091019081015b808210156122df575f80516020908802600381811c8c0183015160079283168b016101009081039190911c88168c029182901c8e019093015191168a019091031c85169060ff8216900361221b5760015f51015f52600183019250506121ba565b60078389029081168901610100039060031c8c0160200160ff83811610156122b8578051821c87166122b4848260ff82165f8160ff038060ff8560181c16028360ff8760181c16020160081c8160ff8660101c16028460ff8860101c16020160081c8260ff8760081c16028560ff8960081c16020160081c9250848360081b8260101b8460181b17171796505050508390509392505050565b9350505b86821b8019825116905083831b811782525060015f51015f526001850194505050506121ba565b50506020830180516001019052612190565b5050505050505050565b60606018851115600386811c86028082166004039091160184025f612322607c600e6137d9565b905061232e82826137d9565b67ffffffffffffffff81111561234657612346613025565b6040519080825280601f01601f191660200182016040528015612370576020820181803683370190505b50935061237f84855183612913565b6123a084607c8486612392576003612394565b5f5b60ff165f8c8c8f612940565b6123a9846129a1565b6123bb8486838a8a60038e901c6129ee565b505050949350505050565b82545f9084906004906123e690640100000000900463ffffffff166136fe565b825463ffffffff9182166101009390930a83810292021916179091555f818152600286016020526040902090915061241f838583613830565b50807f346bf82ec5020791c432a36ed3f70a81bfba0a2321f643108f8ee31a0e0a4a1b848490508585604051612456929190613987565b604051908190038120612470928252602082015260400190565b60405180910390a29392505050565b6040516f30313233343536373839616263646566600f52602081016124a5818686612a38565b90505f196001871b015f5b8581101561258e575f5f19828902825b8a811015612559578082018c02600381901c8a01602001515f916007168e01610100031c871690508060ff165f0361251d575f198410156125115761250a88868888860388612b60565b97505f1993505b81600101945050612551565b5f1984036125305780935081945061254f565b83811461254f5761254688868888860388612b60565b97508093508194505b505b6001016124c0565b505f198210801561256957508983105b156125805761257d868486868e0386612b60565b95505b5050508060010190506124b0565b50507f3c2f7376673e000000000000000000000000000000000000000000000000000081528181036019190182526006808201601f9081166020031690910101604052949350505050565b60208360ff1614612616576040517ff7765fcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f600384901c1681801580159061263557506126338282613996565b155b61266b576040517f9b95bcaa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85156126825760018801612680878983613830565b505b875460ff191660ff861617885561269c611aa18383613736565b885463ffffffff919091166101000264ffffffff001990911617885560028801611fa6848683613830565b5f60405190506020815281816020015280604001808360051b808684378201808515612741575b8351870180356020820183375f38823584305af461270e573d5f873e3d86fd5b5082810384523d815260209384019381013d5f823e5f3d8201523d01601f0167ffffffffffffffe01690508184106126ee575b60408181521b90931795945050505050565b8060401c8167ffffffffffffffff16f35b5f60ff821115610ed8576040516306dfcc6560e41b81526008600482015260248101839052604401611652565b5f61ffff821115610ed8576040516306dfcc6560e41b81526010600482015260248101839052604401611652565b5f196001831b0160ff84165f8190036127d9575050611ba6565b60208301515b836060015181101561290a57835160c085015160a086015190830290910190810160ff84900361284e575b8082101561284957868202600781168801610100038160031c60208c0101915086811b801983511690508a821b8117835250505081600101915061280a565b612900565b8082101561290057818702600381901c8a0160200180516007909216890161010003915f6128e48c83861c8b168a5f8160ff038060ff8560181c16028360ff8760181c16020160081c8160ff8660101c16028460ff8860101c16020160081c8260ff8760081c16028560ff8960081c16020160081c9250848360081b8260101b8460181b17171796505050508390509392505050565b89851b19929092169190931b179052506001919091019061284e565b50506001016127df565b50505050505050565b6020830160428153604d60018201535061292f83600284612c81565b61293b83600a83612c81565b505050565b61294c88600e89612c81565b61295888601285612c81565b61296488601684612c81565b61297188601a6001612cab565b61297d88601c83612cab565b61298988601e87612c81565b61299588602288612c81565b6122f188602e86612c81565b6129b081603662ff0000612c81565b6129be81603a61ff00612c81565b6129cb81603e60ff612c81565b6129db81604263ff000000612c81565b6129eb8160466373524742612c81565b50565b808302600380821660040316810185602089010160208801600186035f5b87811015612a2a57858682028401868385030286015e600101612a0c565b505050505050505050505050565b7f3c7376672073686170652d72656e646572696e673d226372697370456467657383527f222077696474683d22000000000000000000000000000000000000000000000060208401526029909201915f612a928484612cc3565b7f22206865696768743d22000000000000000000000000000000000000000000008152600a019350612ac48483612cc3565b7f222076696577426f783d223020302000000000000000000000000000000000008152600f019350612af68484612cc3565b935060208453600184019350612b0c8483612cc3565b7f2220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f81527f737667223e0000000000000000000000000000000000000000000000000000006020820152602501949350505050565b5f7f3c7061746820643d224d000000000000000000000000000000000000000000008652600a86019550612b948686612cc3565b955060208653600186019550612baa8685612cc3565b7f763168000000000000000000000000000000000000000000000000000000000081526003019550612bdc8684612cc3565b95507f762d31222066696c6c3d222300000000000000000000000000000000000000008652600c860195505f601883901c60ff1690505f601084901c60ff1690505f600885901c60ff1690505f8560ff169050612c4d8a82600887901b601087901b601887901b1717176008612d08565b7f222f3e000000000000000000000000000000000000000000000000000000000081526003019a9950505050505050505050565b8160208401018181538160081c60018201538160101c60028201538160181c600382015350505050565b8160208401018181538160081c600182015350505050565b5f6001600a83045b8015612ce15760019190910190600a9004612ccb565b508301805b600182039150600a84066030018253600a8404935083612ce657949350505050565b5f818401805b600f8516516001198201915f190153600f8560041c165181538460081c9450858118612d0e5750949350505050565b5f60a08284031215612d4d575f5ffd5b50919050565b5f5f83601f840112612d63575f5ffd5b50813567ffffffffffffffff811115612d7a575f5ffd5b602083019150836020828501011115612d91575f5ffd5b9250929050565b5f5f5f5f60608587031215612dab575f5ffd5b843567ffffffffffffffff811115612dc1575f5ffd5b612dcd87828801612d3d565b945050602085013567ffffffffffffffff811115612de9575f5ffd5b612df587828801612d53565b9598909750949560400135949350505050565b5f5f83601f840112612e18575f5ffd5b50813567ffffffffffffffff811115612e2f575f5ffd5b6020830191508360208260051b8501011115612d91575f5ffd5b5f5f60208385031215612e5a575f5ffd5b823567ffffffffffffffff811115612e70575f5ffd5b612e7c85828601612e08565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b805160ff1682525f6020820151612ed2602085018260ff169052565b506040820151612ee8604085018261ffff169052565b506060820151612efe606085018261ffff169052565b506080820151612f14608085018261ffff169052565b5060a0820151612f2a60a085018261ffff169052565b5060c0820151612f4060c085018261ffff169052565b5060e0820151612f5660e085018261ffff169052565b50610100820151612f7061010085018263ffffffff169052565b50610120820151612f8a61012085018263ffffffff169052565b50610140820151612fa461014085018263ffffffff169052565b50610160820151610180610160850152610fed610180850182612e88565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561301957603f19878603018452613004858351612eb6565b94506020938401939190910190600101612fe8565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561306257613062613025565b604052919050565b5f6080828403121561307a575f5ffd5b6040516080810167ffffffffffffffff8111828210171561309d5761309d613025565b6040908152833582526020808501359083015283810135908201526060928301359281019290925250919050565b5f5f5f5f5f61010086880312156130e0575f5ffd5b853567ffffffffffffffff8111156130f6575f5ffd5b61310288828901612d3d565b955050613112876020880161306a565b949794965050505060a08301359260c08101359260e0909101359150565b5f5f5f5f5f60608688031215613144575f5ffd5b853567ffffffffffffffff81111561315a575f5ffd5b86016060818903121561316b575f5ffd5b9450602086013567ffffffffffffffff811115613186575f5ffd5b61319288828901612e08565b909550935050604086013567ffffffffffffffff8111156131b1575f5ffd5b6131bd88828901612e08565b969995985093965092949392505050565b5f8151808452602084019350602083015f5b828110156131fe5781518652602095860195909101906001016131e0565b5093949350505050565b838152606060208201525f61322060608301856131ce565b828103604084015261080081856131ce565b5f60208284031215613242575f5ffd5b813567ffffffffffffffff811115613258575f5ffd5b8201601f81018413613268575f5ffd5b803567ffffffffffffffff81111561328257613282613025565b8060051b61329260208201613039565b918252602081840181019290810190878411156132ad575f5ffd5b6020850194505b838510156132d3578435808352602095860195909350909101906132b4565b979650505050505050565b848152836020820152826040820152608060608201525f6108006080830184612e88565b5f60208284031215613312575f5ffd5b5035919050565b60ff815116825263ffffffff60208201511660208301525f60408201516080604085015261334a6080850182612e88565b90506060830151848203606086015261049c8282612e88565b602081525f61118a6020830184613319565b602081525f61118a6020830184612e88565b602081525f61118a60208301846131ce565b5f5f5f5f5f5f61010087890312156133af575f5ffd5b863567ffffffffffffffff8111156133c5575f5ffd5b6133d189828a01612d3d565b9650506133e1886020890161306a565b945060a0870135935060c087013567ffffffffffffffff811115613403575f5ffd5b61340f89828a01612d53565b979a969950949794969560e090950135949350505050565b5f5f5f60608486031215613439575f5ffd5b833567ffffffffffffffff81111561344f575f5ffd5b61345b86828701612d3d565b9660208601359650604090950135949350505050565b803560ff81168114613481575f5ffd5b919050565b5f5f5f5f5f6060868803121561349a575f5ffd5b853567ffffffffffffffff8111156134b0575f5ffd5b6134bc88828901612d53565b90965094506134cf905060208701613471565b9250604086013567ffffffffffffffff8111156134ea575f5ffd5b6131bd88828901612d53565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561301957603f19878603018452613538858351612e88565b9450602093840193919091019060010161351c565b5f5f6020838503121561355e575f5ffd5b823567ffffffffffffffff811115613574575f5ffd5b612e7c85828601612d53565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561301957603f198786030184526135c2858351613319565b945060209384019391909101906001016135a6565b602081525f61118a6020830184612eb6565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061361157607f821691505b602082108103612d4d57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8181038181111561113a5761113a61362f565b5f5f8335601e1984360301811261366b575f5ffd5b83018035915067ffffffffffffffff821115613685575f5ffd5b602001915036819003821315612d91575f5ffd5b5f602082840312156136a9575f5ffd5b61118a82613471565b5f823560de198336030181126136c6575f5ffd5b9190910192915050565b5f8235609e198336030181126136c6575f5ffd5b5f608082840312156136f4575f5ffd5b61118a838361306a565b5f63ffffffff821663ffffffff81036137195761371961362f565b60010192915050565b634e487b7160e01b5f52601260045260245ffd5b5f8261374457613744613722565b500490565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60a081525f61378460a08301888a613749565b905060ff8616602083015284604083015283606083015273ffffffffffffffffffffffffffffffffffffffff83166080830152979650505050505050565b808202811582820484141761113a5761113a61362f565b8082018082111561113a5761113a61362f565b601f82111561293b57805f5260205f20601f840160051c810160208510156138115750805b601f840160051c820191505b8181101561161f575f815560010161381d565b67ffffffffffffffff83111561384857613848613025565b61385c8361385683546135fd565b836137ec565b5f601f84116001811461388d575f85156138765750838201355b5f19600387901b1c1916600186901b17835561161f565b5f83815260208120601f198716915b828110156138bc578685013582556020948501946001909201910161389c565b50868210156138d8575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6101a081525f6138ff6101a083018d8f613749565b90508a6020830152896040830152886060830152876080830152865160a0830152602087015160c0830152604087015160e0830152606087015161010083015285610120830152846101408301528361016083015261397761018083018473ffffffffffffffffffffffffffffffffffffffff169052565b9c9b505050505050505050505050565b818382375f9101908152919050565b5f826139a4576139a4613722565b50069056fea264697066735822122077e89be32244d9ce82ae1ea1924731e0e0932d6723068d44b818e677ab9d501064736f6c634300081c0033
Deployed Bytecode
0x60806040526004361061016d575f3560e01c8063837ab668116100c6578063ac9650d81161007c578063df0c783811610057578063df0c783814610316578063dfdaf5281461040d578063f781e3ae14610439575f5ffd5b8063ac9650d8146103ba578063c278dba3146103da578063ccbe1ed2146103f9575f5ffd5b806394ac753e116100ac57806394ac753e14610368578063a21abed81461037c578063a26327ff1461039b575f5ffd5b8063837ab6681461032a57806390c302e714610349575f5ffd5b8063505e570a1161012657806360ff37bc1161010157806360ff37bc146102cb5780636abf7826146102f75780637b7e260514610316575f5ffd5b8063505e570a1461024b57806351c39604146102775780635840b0f81461029f575f5ffd5b80632cc4dcb6116101565780632cc4dcb6146101cf57806347d02b81146101ee57806349f83b1f1461021c575f5ffd5b80630d499331146101715780631adb75ac146101a3575b5f5ffd5b34801561017c575f5ffd5b5061019061018b366004612d98565b610465565b6040519081526020015b60405180910390f35b3480156101ae575f5ffd5b506101c26101bd366004612e49565b6104a5565b60405161019a9190612fc2565b3480156101da575f5ffd5b506101906101e93660046130cb565b610731565b3480156101f9575f5ffd5b5061020d610208366004613130565b61080a565b60405161019a93929190613208565b348015610227575f5ffd5b5061023b610236366004613232565b6109ea565b60405161019a94939291906132de565b348015610256575f5ffd5b5061026a610265366004613302565b610c72565b60405161019a9190613363565b348015610282575f5ffd5b5061028a5f81565b60405163ffffffff909116815260200161019a565b3480156102aa575f5ffd5b506102be6102b9366004613302565b610e10565b60405161019a9190613375565b3480156102d6575f5ffd5b506102ea6102e5366004613232565b610ecd565b60405161019a9190613387565b348015610302575f5ffd5b506102be610311366004613232565b610edc565b348015610321575f5ffd5b50610190602081565b348015610335575f5ffd5b50610190610344366004613399565b610eff565b348015610354575f5ffd5b50610190610363366004613427565b610fb7565b348015610373575f5ffd5b50610190610ff5565b348015610387575f5ffd5b506102be610396366004613232565b611024565b3480156103a6575f5ffd5b506101906103b5366004613486565b611047565b6103cd6103c8366004612e49565b61111c565b60405161019a91906134f6565b3480156103e5575f5ffd5b506101906103f436600461354d565b611140565b348015610404575f5ffd5b50610190611191565b348015610418575f5ffd5b5061042c610427366004612e49565b6111b8565b60405161019a9190613580565b348015610444575f5ffd5b50610458610453366004613302565b6113f4565b60405161019a91906135d7565b5f61049c8560405180608001604052805f81526020015f81526020018860600135815260200188608001358152505f878787610eff565b95945050505050565b6060818067ffffffffffffffff8111156104c1576104c1613025565b60405190808252806020026020018201604052801561055057816020015b60408051610180810182525f808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e083018290526101008301829052610120830182905261014083019190915261016082015282525f199092019101816104df5790505b5091507f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4015f5b8281101561072857815f878784818110610592576105926135e9565b63ffffffff6020918202939093013583168452838101949094525060409182015f20825161018081018452815460ff80821683526101008083049091169683019690965261ffff6201000082048116958301959095526401000000008104851660608301526601000000000000810485166080830152680100000000000000008104851660a08301526a01000000000000000000008104851660c0830152600160601b810490941660e0820152600160701b8404831694810194909452600160901b83048216610120850152600160b01b9092041661014083015260018101805461016084019190610683906135fd565b80601f01602080910402602001604051908101604052809291908181526020018280546106af906135fd565b80156106fa5780601f106106d1576101008083540402835291602001916106fa565b820191905f5260205f20905b8154815290600101906020018083116106dd57829003601f168201915b505050505081525050848281518110610715576107156135e9565b6020908102919091010152600101610576565b50505092915050565b5f61074b8585886060013589608001358a60400135611566565b6107d38660400135865f015187604001516107669190613643565b8760200151886060015161077a9190613643565b6107c17f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4006107a789611626565b63ffffffff165f9081526002919091016020526040902090565b80546107cc906135fd565b905061165b565b5f82116107f357604051632b4582a560e01b815260040160405180910390fd5b6108008686868686611706565b9695505050505050565b5f60608061083861081b8980613656565b61082b60408c0160208d01613699565b6103b560408d018d613656565b9250858067ffffffffffffffff81111561085457610854613025565b60405190808252806020026020018201604052801561087d578160200160208202803683370190505b5092505f5b8181101561090e573689898381811061089d5761089d6135e9565b90506020028101906108af91906136b2565b90506108e86108be82806136d0565b6108d0368490038401602085016136e4565b60a08401356108e260c0860186613656565b8b610eff565b8583815181106108fa576108fa6135e9565b602090810291909101015250600101610882565b508490508067ffffffffffffffff81111561092b5761092b613025565b604051908082528060200260200182016040528015610954578160200160208202803683370190505b5091505f5b818110156109dd5736878783818110610974576109746135e9565b905060200281019061098691906136b2565b90506109b761099582806136d0565b6109a7368490038401602085016136e4565b8360a001358460c001358a610731565b8483815181106109c9576109c96135e9565b602090810291909101015250600101610959565b5050955095509592505050565b5f5f5f60605f855190505f8111610a2d576040517f21fa0dc700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a3686611a29565b5f5f606080610a7b6040518061010001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b610a9d8b5f81518110610a9057610a906135e9565b6020026020010151611bac565b60c083015160e0840151909d509b509097509195509093509050610ac085611d9c565b8160ff169150809350819b50505060038a901c888a020267ffffffffffffffff811115610aef57610aef613025565b6040519080825280601f01601f191660200182016040528015610b19576020820181803683370190505b508151909750158015610b2e57506020810151155b8015610b3d5750888160400151145b8015610b4c5750878160600151145b15610b6357610b5e8783858d88611e7f565b610b7d565b610b6f87838c84611fb1565b610b7d8783858d888661217e565b60015b86811015610c64575f610b9e8d8381518110610a9057610a906135e9565b92985091965093509050868114610bfb57809650610bbb87611d9c565b945060ff1690508b8114610bfb576040517f23f838ec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251158015610c0c57506020830151155b8015610c1b57508a8360400151145b8015610c2a5750898360600151145b15610c4157610c3c8985878f8a611e7f565b610c5b565b610c4d89858e86611fb1565b610c5b8985878f8a8861217e565b50600101610b80565b505050505050509193509193565b60408051608080820183525f808352602080840182905260608486018190528085015263ffffffff86811683527f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca77263320182529185902085519384018652805460ff81168552610100900490921690830152600181018054939492939192840191610cf9906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610d25906135fd565b8015610d705780601f10610d4757610100808354040283529160200191610d70565b820191905f5260205f20905b815481529060010190602001808311610d5357829003601f168201915b50505050508152602001600282018054610d89906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610db5906135fd565b8015610e005780601f10610dd757610100808354040283529160200191610e00565b820191905f5260205f20905b815481529060010190602001808311610de357829003601f168201915b5050505050815250509050919050565b6060610e3f7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4006107a784611626565b8054610e4a906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610e76906135fd565b8015610ec15780601f10610e9857610100808354040283529160200191610ec1565b820191905f5260205f20905b815481529060010190602001808311610ea457829003601f168201915b50505050509050919050565b6060610ed882611a29565b5090565b60605f5f5f5f610eeb866109ea565b9350935093509350610800848484846122fb565b5f610f19868689606001358a608001358b60400135611566565b610f4e8760400135875f01518860400151610f349190613643565b88602001518960600151610f489190613643565b8661165b565b5f8211610f6e57604051632b4582a560e01b815260040160405180910390fd5b7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4005f610f9b8287876123c6565b9050610faa8989898488611706565b9998505050505050505050565b5f610fed8460405180608001604052805f81526020015f81526020018760600135815260200187608001358152505f8686610731565b949350505050565b5f7f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca7726332005b5463ffffffff16919050565b60605f5f5f5f611033866109ea565b93509350935093506108008484848461247f565b7f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca77263320080545f91908290829082906110829063ffffffff166136fe565b825463ffffffff9182166101009390930a83810292021916179091555f81815260018401602052604090209091506110be818a8a8a8a8a6125d9565b817f73b05f94061684c43b9361fa65b5b965397451ddaa3035fce829f4fdc43997168a8a8a6110f4601f600383901c168b613736565b60405161110894939291908c903390613771565b60405180910390a250979650505050505050565b60603415611128575f5ffd5b61113a61113584846126c7565b612753565b92915050565b5f8161115f576040516306e5cf7960e21b815260040160405180910390fd5b61118a7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40084846123c6565b9392505050565b5f7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d400611018565b6060818067ffffffffffffffff8111156111d4576111d4613025565b60405190808252806020026020018201604052801561122757816020015b604080516080810182525f80825260208201526060918101829052818101919091528152602001906001900390816111f25790505b5091507f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca7726332015f5b8281101561072857815f878784818110611269576112696135e9565b63ffffffff6020918202939093013583168452838101949094525060409182015f208251608081018452815460ff811682526101009004909216938201939093526001830180549193928401916112bf906135fd565b80601f01602080910402602001604051908101604052809291908181526020018280546112eb906135fd565b80156113365780601f1061130d57610100808354040283529160200191611336565b820191905f5260205f20905b81548152906001019060200180831161131957829003601f168201915b5050505050815260200160028201805461134f906135fd565b80601f016020809104026020016040519081016040528092919081815260200182805461137b906135fd565b80156113c65780601f1061139d576101008083540402835291602001916113c6565b820191905f5260205f20905b8154815290600101906020018083116113a957829003601f168201915b5050505050815250508482815181106113e1576113e16135e9565b602090810291909101015260010161124d565b60408051610180810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201839052610100820183905261012082018390526101408201929092526101608101919091527f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40063ffffffff8084165f90815260019283016020908152604091829020825161018081018452815460ff80821683526101008083049091169483019490945261ffff6201000082048116958301959095526401000000008104851660608301526601000000000000810485166080830152680100000000000000008104851660a08301526a01000000000000000000008104851660c0830152600160601b810490941660e0820152600160701b8404851692810192909252600160901b83048416610120830152600160b01b909204909216610140830152918201805491929161016084019190610d89906135fd565b604085015185511180159061157f575082856040015111155b801561159357508460600151856020015111155b80156115a3575081856060015111155b6115d9576040517f45e4a28400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115e6600180831b613643565b84111561161f576040517f24aad79700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b5f63ffffffff821115610ed8576040516306dfcc6560e41b815260206004820152602481018390526044015b60405180910390fd5b835f10801561166b575060208411155b801561167e57506001640101010116851c165b6116b4576040517f10c88af100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f846116c084866137c2565b6116ca91906137c2565b90505f60036116da8360076137d9565b901c90508083146116fe576040516306e5cf7960e21b815260040160405180910390fd5b505050505050565b7f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40080545f91908190839061173f9063ffffffff166136fe565b825463ffffffff9182166101009390930a83810292021916179091555f81815260018301602052604081209193506117778980613656565b9050111561179b576117898880613656565b6001830191611799919083613830565b505b6117a88860200135612764565b815460ff191660ff919091161781556117c46040890135612764565b815460ff919091166101000261ff00199091161781556117e76060890135612791565b815461ffff91909116620100000263ffff00001990911617815561180e6080890135612791565b815461ffff919091166401000000000265ffff0000000019909116178155865161183790612791565b815461ffff9190911666010000000000000267ffff00000000000019909116178155602087015161186790612791565b815461ffff91909116680100000000000000000269ffff000000000000000019909116178155604087015161189b90612791565b815461ffff919091166a0100000000000000000000026bffff000000000000000000001990911617815560608701516118d390612791565b815461ffff91909116600160601b026dffff0000000000000000000000001990911617815561190186611626565b815463ffffffff91909116600160901b027fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff90911617815561194284611626565b815463ffffffff91909116600160b01b027fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff90911617815561198385611626565b815463ffffffff91909116600160701b027fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff90911617905550807f354260e53682a8b55f8da011fb4d880b47efb2d44dd4c2502511508e3cd59d276119e88880613656565b89602001358a604001358b606001358c608001358c8b8d8c33604051611a189b9a999897969594939291906138ea565b60405180910390a295945050505050565b60208101517f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d4019063ffffffff811115611a7f576040516306dfcc6560e41b81526020600482015260248101829052604401611652565b50815160015b81811015611ba6575f611aa6611aa1868460051b016020015190565b611626565b63ffffffff81165f90815260208690526040902054909150610100900460ff16611afc576040517f2eb8a6de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f9081526020859052604090205460ff16825b5f81118015611b51575081865f611b368a6001860360051b016020015190565b63ffffffff16815260208101919091526040015f205460ff16115b15611b8657611b7e8782611b6e8a6001860360051b016020015190565b808260051b602085010152505050565b5f1901611b16565b63ffffffff8316600582901b880160200152505050806001019050611a85565b50505050565b5f611bed6040518061010001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b63ffffffff8381165f9081527f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d40160209081526040808320805461ffff620100008204811660c08901526401000000008204811660e08901526601000000000000820481168089526801000000000000000083048216958901959095526a010000000000000000000082048116938801849052600160601b820416606088810191909152600160901b8204909616608088015260ff6101009091041696509293927f48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d400929091611cdb9190613643565b60a0860152805463ffffffff600160701b820481165f9081526002850160205260409020600160b01b9092041694508054611d15906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611d41906135fd565b8015611d8c5780601f10611d6357610100808354040283529160200191611d8c565b820191905f5260205f20905b815481529060010190602001808311611d6f57829003601f168201915b5050505050925050509193509193565b5f6060817f3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca77263320181611dcb86611626565b63ffffffff16815260208101919091526040015f20805460028201805460ff9092169550919250611dfb906135fd565b80601f0160208091040260200160405190810160405280929190818152602001828054611e27906135fd565b8015611e725780601f10611e4957610100808354040283529160200191611e72565b820191905f5260205f20905b815481529060010190602001808311611e5557829003601f168201915b5050505050915050915091565b8451600383901c9004600180841b5f1990810191841b015f5b83811015611fa6576020858202600381811c8a01830151600792831689016101009081039190911c86168a029182901c8c01909301515f9391909216890190031c841660ff8116808303611eee57505050611f9e565b838902600381901c8d0160200180519450906007168a016101000360ff831015611f895784811c8816611f858582865f8160ff038060ff8560181c16028360ff8760181c16020160081c8160ff8660101c16028460ff8860101c16020160081c8260ff8760081c16028560ff8960081c16020160081c9250848360081b8260101b8460181b17171796505050508390509392505050565b9450505b87811b19949094169290931b91909117909152505b600101611e98565b505050505050505050565b60808101516020908302600381901c85018201519183015160079091168401610100039190911c6001841b5f190116901561203b5761203b8582856040518061010001604052805f81526020015f81526020018760c001518152602001876020015181526020015f81526020018760c0015181526020018760c0015181526020015f8152506127bf565b8160e00151826060015110156120a4576120a48582856040518061010001604052805f8152602001876060015181526020018760c0015181526020018760e0015181526020015f81526020018760c0015181526020018760c0015181526020015f8152506127bf565b815115612102576121028582856040518061010001604052805f815260200187602001518152602001875f01518152602001876060015181526020015f8152602001875f015181526020018760c0015181526020015f8152506127bf565b8160c001518260400151101561161f5761161f85828560405180610100016040528087604001518152602001876020015181526020018760c001518152602001876060015181526020015f815260200187604001518860c001516121669190613643565b81526020018760c0015181526020015f8152506127bf565b5f8052600180841b5f1990810191841b015b8260600151836020015110156122f157825160c0840151602085015160a086015191029091019081015b808210156122df575f80516020908802600381811c8c0183015160079283168b016101009081039190911c88168c029182901c8e019093015191168a019091031c85169060ff8216900361221b5760015f51015f52600183019250506121ba565b60078389029081168901610100039060031c8c0160200160ff83811610156122b8578051821c87166122b4848260ff82165f8160ff038060ff8560181c16028360ff8760181c16020160081c8160ff8660101c16028460ff8860101c16020160081c8260ff8760081c16028560ff8960081c16020160081c9250848360081b8260101b8460181b17171796505050508390509392505050565b9350505b86821b8019825116905083831b811782525060015f51015f526001850194505050506121ba565b50506020830180516001019052612190565b5050505050505050565b60606018851115600386811c86028082166004039091160184025f612322607c600e6137d9565b905061232e82826137d9565b67ffffffffffffffff81111561234657612346613025565b6040519080825280601f01601f191660200182016040528015612370576020820181803683370190505b50935061237f84855183612913565b6123a084607c8486612392576003612394565b5f5b60ff165f8c8c8f612940565b6123a9846129a1565b6123bb8486838a8a60038e901c6129ee565b505050949350505050565b82545f9084906004906123e690640100000000900463ffffffff166136fe565b825463ffffffff9182166101009390930a83810292021916179091555f818152600286016020526040902090915061241f838583613830565b50807f346bf82ec5020791c432a36ed3f70a81bfba0a2321f643108f8ee31a0e0a4a1b848490508585604051612456929190613987565b604051908190038120612470928252602082015260400190565b60405180910390a29392505050565b6040516f30313233343536373839616263646566600f52602081016124a5818686612a38565b90505f196001871b015f5b8581101561258e575f5f19828902825b8a811015612559578082018c02600381901c8a01602001515f916007168e01610100031c871690508060ff165f0361251d575f198410156125115761250a88868888860388612b60565b97505f1993505b81600101945050612551565b5f1984036125305780935081945061254f565b83811461254f5761254688868888860388612b60565b97508093508194505b505b6001016124c0565b505f198210801561256957508983105b156125805761257d868486868e0386612b60565b95505b5050508060010190506124b0565b50507f3c2f7376673e000000000000000000000000000000000000000000000000000081528181036019190182526006808201601f9081166020031690910101604052949350505050565b60208360ff1614612616576040517ff7765fcc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f600384901c1681801580159061263557506126338282613996565b155b61266b576040517f9b95bcaa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85156126825760018801612680878983613830565b505b875460ff191660ff861617885561269c611aa18383613736565b885463ffffffff919091166101000264ffffffff001990911617885560028801611fa6848683613830565b5f60405190506020815281816020015280604001808360051b808684378201808515612741575b8351870180356020820183375f38823584305af461270e573d5f873e3d86fd5b5082810384523d815260209384019381013d5f823e5f3d8201523d01601f0167ffffffffffffffe01690508184106126ee575b60408181521b90931795945050505050565b8060401c8167ffffffffffffffff16f35b5f60ff821115610ed8576040516306dfcc6560e41b81526008600482015260248101839052604401611652565b5f61ffff821115610ed8576040516306dfcc6560e41b81526010600482015260248101839052604401611652565b5f196001831b0160ff84165f8190036127d9575050611ba6565b60208301515b836060015181101561290a57835160c085015160a086015190830290910190810160ff84900361284e575b8082101561284957868202600781168801610100038160031c60208c0101915086811b801983511690508a821b8117835250505081600101915061280a565b612900565b8082101561290057818702600381901c8a0160200180516007909216890161010003915f6128e48c83861c8b168a5f8160ff038060ff8560181c16028360ff8760181c16020160081c8160ff8660101c16028460ff8860101c16020160081c8260ff8760081c16028560ff8960081c16020160081c9250848360081b8260101b8460181b17171796505050508390509392505050565b89851b19929092169190931b179052506001919091019061284e565b50506001016127df565b50505050505050565b6020830160428153604d60018201535061292f83600284612c81565b61293b83600a83612c81565b505050565b61294c88600e89612c81565b61295888601285612c81565b61296488601684612c81565b61297188601a6001612cab565b61297d88601c83612cab565b61298988601e87612c81565b61299588602288612c81565b6122f188602e86612c81565b6129b081603662ff0000612c81565b6129be81603a61ff00612c81565b6129cb81603e60ff612c81565b6129db81604263ff000000612c81565b6129eb8160466373524742612c81565b50565b808302600380821660040316810185602089010160208801600186035f5b87811015612a2a57858682028401868385030286015e600101612a0c565b505050505050505050505050565b7f3c7376672073686170652d72656e646572696e673d226372697370456467657383527f222077696474683d22000000000000000000000000000000000000000000000060208401526029909201915f612a928484612cc3565b7f22206865696768743d22000000000000000000000000000000000000000000008152600a019350612ac48483612cc3565b7f222076696577426f783d223020302000000000000000000000000000000000008152600f019350612af68484612cc3565b935060208453600184019350612b0c8483612cc3565b7f2220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f81527f737667223e0000000000000000000000000000000000000000000000000000006020820152602501949350505050565b5f7f3c7061746820643d224d000000000000000000000000000000000000000000008652600a86019550612b948686612cc3565b955060208653600186019550612baa8685612cc3565b7f763168000000000000000000000000000000000000000000000000000000000081526003019550612bdc8684612cc3565b95507f762d31222066696c6c3d222300000000000000000000000000000000000000008652600c860195505f601883901c60ff1690505f601084901c60ff1690505f600885901c60ff1690505f8560ff169050612c4d8a82600887901b601087901b601887901b1717176008612d08565b7f222f3e000000000000000000000000000000000000000000000000000000000081526003019a9950505050505050505050565b8160208401018181538160081c60018201538160101c60028201538160181c600382015350505050565b8160208401018181538160081c600182015350505050565b5f6001600a83045b8015612ce15760019190910190600a9004612ccb565b508301805b600182039150600a84066030018253600a8404935083612ce657949350505050565b5f818401805b600f8516516001198201915f190153600f8560041c165181538460081c9450858118612d0e5750949350505050565b5f60a08284031215612d4d575f5ffd5b50919050565b5f5f83601f840112612d63575f5ffd5b50813567ffffffffffffffff811115612d7a575f5ffd5b602083019150836020828501011115612d91575f5ffd5b9250929050565b5f5f5f5f60608587031215612dab575f5ffd5b843567ffffffffffffffff811115612dc1575f5ffd5b612dcd87828801612d3d565b945050602085013567ffffffffffffffff811115612de9575f5ffd5b612df587828801612d53565b9598909750949560400135949350505050565b5f5f83601f840112612e18575f5ffd5b50813567ffffffffffffffff811115612e2f575f5ffd5b6020830191508360208260051b8501011115612d91575f5ffd5b5f5f60208385031215612e5a575f5ffd5b823567ffffffffffffffff811115612e70575f5ffd5b612e7c85828601612e08565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b805160ff1682525f6020820151612ed2602085018260ff169052565b506040820151612ee8604085018261ffff169052565b506060820151612efe606085018261ffff169052565b506080820151612f14608085018261ffff169052565b5060a0820151612f2a60a085018261ffff169052565b5060c0820151612f4060c085018261ffff169052565b5060e0820151612f5660e085018261ffff169052565b50610100820151612f7061010085018263ffffffff169052565b50610120820151612f8a61012085018263ffffffff169052565b50610140820151612fa461014085018263ffffffff169052565b50610160820151610180610160850152610fed610180850182612e88565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561301957603f19878603018452613004858351612eb6565b94506020938401939190910190600101612fe8565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561306257613062613025565b604052919050565b5f6080828403121561307a575f5ffd5b6040516080810167ffffffffffffffff8111828210171561309d5761309d613025565b6040908152833582526020808501359083015283810135908201526060928301359281019290925250919050565b5f5f5f5f5f61010086880312156130e0575f5ffd5b853567ffffffffffffffff8111156130f6575f5ffd5b61310288828901612d3d565b955050613112876020880161306a565b949794965050505060a08301359260c08101359260e0909101359150565b5f5f5f5f5f60608688031215613144575f5ffd5b853567ffffffffffffffff81111561315a575f5ffd5b86016060818903121561316b575f5ffd5b9450602086013567ffffffffffffffff811115613186575f5ffd5b61319288828901612e08565b909550935050604086013567ffffffffffffffff8111156131b1575f5ffd5b6131bd88828901612e08565b969995985093965092949392505050565b5f8151808452602084019350602083015f5b828110156131fe5781518652602095860195909101906001016131e0565b5093949350505050565b838152606060208201525f61322060608301856131ce565b828103604084015261080081856131ce565b5f60208284031215613242575f5ffd5b813567ffffffffffffffff811115613258575f5ffd5b8201601f81018413613268575f5ffd5b803567ffffffffffffffff81111561328257613282613025565b8060051b61329260208201613039565b918252602081840181019290810190878411156132ad575f5ffd5b6020850194505b838510156132d3578435808352602095860195909350909101906132b4565b979650505050505050565b848152836020820152826040820152608060608201525f6108006080830184612e88565b5f60208284031215613312575f5ffd5b5035919050565b60ff815116825263ffffffff60208201511660208301525f60408201516080604085015261334a6080850182612e88565b90506060830151848203606086015261049c8282612e88565b602081525f61118a6020830184613319565b602081525f61118a6020830184612e88565b602081525f61118a60208301846131ce565b5f5f5f5f5f5f61010087890312156133af575f5ffd5b863567ffffffffffffffff8111156133c5575f5ffd5b6133d189828a01612d3d565b9650506133e1886020890161306a565b945060a0870135935060c087013567ffffffffffffffff811115613403575f5ffd5b61340f89828a01612d53565b979a969950949794969560e090950135949350505050565b5f5f5f60608486031215613439575f5ffd5b833567ffffffffffffffff81111561344f575f5ffd5b61345b86828701612d3d565b9660208601359650604090950135949350505050565b803560ff81168114613481575f5ffd5b919050565b5f5f5f5f5f6060868803121561349a575f5ffd5b853567ffffffffffffffff8111156134b0575f5ffd5b6134bc88828901612d53565b90965094506134cf905060208701613471565b9250604086013567ffffffffffffffff8111156134ea575f5ffd5b6131bd88828901612d53565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561301957603f19878603018452613538858351612e88565b9450602093840193919091019060010161351c565b5f5f6020838503121561355e575f5ffd5b823567ffffffffffffffff811115613574575f5ffd5b612e7c85828601612d53565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561301957603f198786030184526135c2858351613319565b945060209384019391909101906001016135a6565b602081525f61118a6020830184612eb6565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061361157607f821691505b602082108103612d4d57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8181038181111561113a5761113a61362f565b5f5f8335601e1984360301811261366b575f5ffd5b83018035915067ffffffffffffffff821115613685575f5ffd5b602001915036819003821315612d91575f5ffd5b5f602082840312156136a9575f5ffd5b61118a82613471565b5f823560de198336030181126136c6575f5ffd5b9190910192915050565b5f8235609e198336030181126136c6575f5ffd5b5f608082840312156136f4575f5ffd5b61118a838361306a565b5f63ffffffff821663ffffffff81036137195761371961362f565b60010192915050565b634e487b7160e01b5f52601260045260245ffd5b5f8261374457613744613722565b500490565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60a081525f61378460a08301888a613749565b905060ff8616602083015284604083015283606083015273ffffffffffffffffffffffffffffffffffffffff83166080830152979650505050505050565b808202811582820484141761113a5761113a61362f565b8082018082111561113a5761113a61362f565b601f82111561293b57805f5260205f20601f840160051c810160208510156138115750805b601f840160051c820191505b8181101561161f575f815560010161381d565b67ffffffffffffffff83111561384857613848613025565b61385c8361385683546135fd565b836137ec565b5f601f84116001811461388d575f85156138765750838201355b5f19600387901b1c1916600186901b17835561161f565b5f83815260208120601f198716915b828110156138bc578685013582556020948501946001909201910161389c565b50868210156138d8575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6101a081525f6138ff6101a083018d8f613749565b90508a6020830152896040830152886060830152876080830152865160a0830152602087015160c0830152604087015160e0830152606087015161010083015285610120830152846101408301528361016083015261397761018083018473ffffffffffffffffffffffffffffffffffffffff169052565b9c9b505050505050505050505050565b818382375f9101908152919050565b5f826139a4576139a4613722565b50069056fea264697066735822122077e89be32244d9ce82ae1ea1924731e0e0932d6723068d44b818e677ab9d501064736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.