{"sources":{"contracts/ArtCanvas.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n// ---------------------------------------------------------------------------\n// External surfaces (deliberately minimal, Imprint-shaped)\n// ---------------------------------------------------------------------------\n\n/// @dev The Binance Agent ID registry: holding the soulbound NFT is the gate.\ninterface IAgentIdRegistry {\n    function balanceOf(address owner) external view returns (uint256);\n}\n\ninterface IArtToken {\n    function canvas() external view returns (address);\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address who) external view returns (uint256);\n    function mint(address to, uint256 amount) external;\n    function transfer(address to, uint256 amount) external returns (bool);\n}\n\ninterface IERC20Lite {\n    function balanceOf(address who) external view returns (uint256);\n    function transfer(address to, uint256 amount) external returns (bool);\n    function approve(address spender, uint256 amount) external returns (bool);\n}\n\ninterface IWBNB is IERC20Lite {\n    function deposit() external payable;\n}\n\ninterface IPancakeV3Pool {\n    function slot0()\n        external\n        view\n        returns (uint160 sqrtPriceX96, int24 tick, uint16, uint16, uint16, uint32, bool unlocked);\n    function swap(address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data)\n        external\n        returns (int256 amount0, int256 amount1);\n}\n\n/// @dev The PancakeSwap V3 NonfungiblePositionManager surface ART uses.\n///      Deliberately no decreaseLiquidity / transferFrom: this contract never\n///      calls them, so the liquidity can never leave.\ninterface IPositionManager {\n    struct MintParams {\n        address token0;\n        address token1;\n        uint24 fee;\n        int24 tickLower;\n        int24 tickUpper;\n        uint256 amount0Desired;\n        uint256 amount1Desired;\n        uint256 amount0Min;\n        uint256 amount1Min;\n        address recipient;\n        uint256 deadline;\n    }\n\n    struct CollectParams {\n        uint256 tokenId;\n        address recipient;\n        uint128 amount0Max;\n        uint128 amount1Max;\n    }\n\n    function factory() external view returns (address);\n    function WETH9() external view returns (address);\n    function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96)\n        external\n        payable\n        returns (address pool);\n    function mint(MintParams calldata params)\n        external\n        payable\n        returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);\n    function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);\n}\n\n/// @title ART: a 100x100 onchain canvas painted by .ai agents on BNB Chain\n/// @notice Only wallets holding a Binance Agent ID can take part. Every cell\n///         is painted once: the first agent to paint it keeps it for good.\n///         paint() takes up to 5 pixels per window; a pixel whose cell is\n///         already taken is skipped and refunded in the same transaction,\n///         and if all are taken it reverts. The event runs 12 hours\n///         (waitlist-only for the first 6, public for the last 6) or until\n///         the canvas is full, whichever comes first.\n///\n///         1. `addToWaitlist()` (owner, before start): registers addresses\n///            for the waitlist window. Registration closes at startEvent().\n///         2. `startEvent()`: for the first 6 hours only waitlisted agents\n///            can paint, up to 5 pixels each at 0.001 BNB. Then painting is\n///            public for 6 more hours: every Agent ID holder can paint up\n///            to 5 more at 0.0015 BNB.\n///         3. Referral: on a painter's first-ever paint, a referrer may be\n///            bound permanently; every pixel that painter ever paints is\n///            credited to the referrer in the referral accounting.\n///         4. `finalize()`: a fixed 1,000,000,000 ART is minted. 50% goes\n///            to the painters pro rata to the pixels they painted\n///            (`distribute`), 40% into a full-range PancakeSwap V3 0.25%\n///            pool with 70% of the BNB (plus the rounding remainders of\n///            the other shares), and 10% into a referral pool held by this\n///            contract and paid out by `claimReferral()`. The other 30%\n///            of the BNB goes to the operator. THE OPERATOR RECEIVES NO\n///            TOKENS — there is no team or ecosystem allocation at all.\n///            The pool position (an NFT) stays in this contract forever:\n///            there is no function to withdraw or move it, and no withdraw\n///            function of any kind. `collectFees()` sends the trading fees\n///            the position earns to the operator.\n///\n/// @dev All geometry, price, timing and split parameters are constructor\n///      immutables. The production contract `ArtCanvas` (bottom of this\n///      file) fixes them to the locked SPEC values; the test twin in\n///      contracts/mocks/TestArtCanvas.sol scales the canvas down so the\n///      full lifecycle fits in a local test. Logic lives only here.\nabstract contract ArtCanvasBase is Ownable {\n    // Geometry / economics — immutables, set once (production values in ArtCanvas)\n    uint256 public immutable WIDTH;\n    uint256 public immutable HEIGHT;\n    uint256 public immutable PIXELS;\n    uint256 public immutable PIXELS_PER_WINDOW;\n    uint256 public immutable WAITLIST_PRICE;\n    uint256 public immutable PUBLIC_PRICE;\n    uint256 public immutable WAITLIST_DURATION;\n    uint256 public immutable DURATION;\n\n    uint256 public constant COLORS = 16;\n\n    // Fixed supply, minted once by finalize(): 50 / 40 / 10, operator 0\n    uint256 public constant TOTAL_SUPPLY = 1_000_000_000 ether;\n    uint256 public constant PAINTER_SUPPLY = 500_000_000 ether;\n    uint256 public constant LP_SUPPLY = 400_000_000 ether;\n    uint256 public constant REFERRAL_SUPPLY = 100_000_000 ether;\n\n    // BNB revenue split, in basis points; the operator gets the remainder\n    uint256 public constant LP_BPS = 7000;\n    uint256 public constant OPERATOR_BPS = 3000;\n\n    // PancakeSwap V3 0.25% tier, full range (tick spacing 50)\n    uint24 public constant POOL_FEE = 2_500;\n    int24 public constant TICK_LOWER = -887_250;\n    int24 public constant TICK_UPPER = 887_250;\n\n    address private constant DEAD = 0x000000000000000000000000000000000000dEaD;\n\n    IAgentIdRegistry public immutable agentId;\n    IPositionManager public immutable positionManager;\n    IWBNB public immutable wbnb;\n    /// @notice Receives the operator's BNB share and the pool's trading\n    ///         fees. Receives NO tokens, ever.\n    address public immutable operator;\n\n    IArtToken public token;\n\n    uint256 public startTime; // 0 = not started\n    uint256 public publicTime; // painting opens to every Agent ID holder\n    uint256 public endTime;\n    bool public finalized;\n\n    // 4 bits per pixel, 64 pixels per 32-byte slot\n    uint256[] internal _canvasSlots;\n\n    address[] public participants; // every agent that painted, in order of its first pixel\n    mapping(address => uint256) public waitlistPixelsOf;\n    mapping(address => uint256) public publicPixelsOf;\n    uint256 public totalPixelsPainted;\n\n    // built-in waitlist (registration closes at startEvent)\n    mapping(address => bool) private _waitlist;\n    uint256 public waitlistCount;\n\n    // referral accounting\n    mapping(address => address) public referrerOf;\n    mapping(address => uint256) public referredPixelsOf;\n    mapping(address => bool) public referralClaimed;\n    uint256 public totalReferredPixels;\n\n    // filled in by finalize()\n    bytes32 public canvasHash;\n    /// @notice ART each painted pixel earns its painter.\n    uint256 public tokensPerPixel;\n    /// @notice ART each referred pixel earns its referrer.\n    uint256 public tokensPerReferredPixel;\n    uint256 public distributedCount; // participants that received their ART\n    address public pool;\n    uint256 public positionId; // the locked PancakeSwap V3 position\n    address private _swapPool; // only set while finalize() corrects the pool price\n\n    struct Pixel {\n        uint16 x;\n        uint16 y;\n        uint8 color;\n    }\n\n    event TokenSet(address token);\n    event Waitlisted(address who);\n    event EventStarted(uint256 publicTime, uint256 endTime);\n    event Painted(address indexed painter, uint16 x, uint16 y, uint8 color);\n    event CanvasFull(uint256 time);\n    /// @notice The cell was already taken: that pixel was skipped and refunded.\n    event CellTaken(address indexed painter, uint16 x, uint16 y);\n    event ReferralBound(address indexed painter, address indexed referrer);\n    event Finalized(\n        bytes32 canvasHash,\n        uint256 participants,\n        uint256 pixels,\n        uint256 tokensPerPixel,\n        uint256 tokensPerReferredPixel,\n        uint256 lpTokens,\n        uint256 lpBnb,\n        uint256 operatorBnb,\n        uint256 positionId\n    );\n    event Distributed(uint256 fromIndex, uint256 toIndex);\n    event ReferralClaimed(address indexed referrer, uint256 amount);\n    event FeesCollected(uint256 amount0, uint256 amount1);\n\n    error NoToken();\n    error TokenAlreadySet();\n    error EventAlreadyStarted();\n    error EventNotActive();\n    error EventNotOver();\n    error AlreadyFinalized();\n    error NotFinalized();\n    error NoAgentId();\n    error NotOnWaitlist();\n    error NoPixelsLeft();\n    error WrongPayment();\n    error OutOfBounds();\n    error InvalidColor();\n    error NothingToDo();\n    error NothingToClaim();\n    error ReferralAlreadyClaimed();\n    error BadCallback();\n    error RefundFailed();\n    error BadPixelCount();\n    error AllCellsTaken();\n\n    constructor(\n        address agentId_,\n        address positionManager_,\n        address operator_,\n        uint256 width_,\n        uint256 height_,\n        uint256 pixelsPerWindow_,\n        uint256 waitlistPrice_,\n        uint256 publicPrice_,\n        uint256 waitlistDuration_,\n        uint256 duration_\n    ) Ownable(msg.sender) {\n        require(\n            agentId_ != address(0) && positionManager_ != address(0) && operator_ != address(0),\n            \"bad config\"\n        );\n        require(width_ > 0 && height_ > 0 && pixelsPerWindow_ > 0, \"bad geometry\");\n        require(waitlistDuration_ <= duration_ && duration_ > 0, \"bad timing\");\n        // a zero price would leave finalize() seeding a pool with no BNB\n        require(waitlistPrice_ > 0 && publicPrice_ > 0, \"bad price\");\n        agentId = IAgentIdRegistry(agentId_);\n        positionManager = IPositionManager(positionManager_);\n        wbnb = IWBNB(IPositionManager(positionManager_).WETH9());\n        require(address(wbnb) != address(0), \"bad wbnb\");\n        operator = operator_;\n        WIDTH = width_;\n        HEIGHT = height_;\n        PIXELS = width_ * height_;\n        PIXELS_PER_WINDOW = pixelsPerWindow_;\n        WAITLIST_PRICE = waitlistPrice_;\n        PUBLIC_PRICE = publicPrice_;\n        WAITLIST_DURATION = waitlistDuration_;\n        DURATION = duration_;\n        _canvasSlots = new uint256[]((PIXELS + 63) / 64);\n    }\n\n    // ------------------------------------------------------------------\n    // Setup\n    // ------------------------------------------------------------------\n\n    /// @notice Links the ART token, which must be minted only by this\n    ///         contract and have no supply yet.\n    function setToken(address token_) external onlyOwner {\n        if (address(token) != address(0)) revert TokenAlreadySet();\n        require(IArtToken(token_).canvas() == address(this) && IArtToken(token_).totalSupply() == 0, \"bad token\");\n        token = IArtToken(token_);\n        emit TokenSet(token_);\n    }\n\n    /// @notice Registers addresses for the waitlist window. Owner-only and\n    ///         only before the event starts: registration closes forever\n    ///         at startEvent().\n    function addToWaitlist(address[] calldata who) external onlyOwner {\n        if (startTime != 0) revert EventAlreadyStarted();\n        for (uint256 i; i < who.length; ++i) {\n            address a = who[i];\n            if (a != address(0) && !_waitlist[a]) {\n                _waitlist[a] = true;\n                ++waitlistCount;\n                emit Waitlisted(a);\n            }\n        }\n    }\n\n    function onWaitlist(address who) public view returns (bool) {\n        return _waitlist[who];\n    }\n\n    /// @notice Opens the canvas: waitlist only for WAITLIST_DURATION, then\n    ///         public until DURATION seconds after the start.\n    function startEvent() external onlyOwner {\n        if (address(token) == address(0)) revert NoToken();\n        if (startTime != 0) revert EventAlreadyStarted();\n        startTime = block.timestamp;\n        publicTime = block.timestamp + WAITLIST_DURATION;\n        endTime = block.timestamp + DURATION;\n        emit EventStarted(publicTime, endTime);\n    }\n\n    // ------------------------------------------------------------------\n    // Painting\n    // ------------------------------------------------------------------\n\n    /// @notice Paints 1 to `PIXELS_PER_WINDOW` pixels in one transaction,\n    ///         colors 1-15 (0 is the empty canvas). Pay the current window's\n    ///         price (`paintPrice()`) times the number of pixels sent. Each\n    ///         agent has `PIXELS_PER_WINDOW` pixels in the waitlist window\n    ///         and as many again in the public one. A pixel whose cell is\n    ///         already taken is skipped (`CellTaken`): it uses no pixel and\n    ///         its price is refunded in the same transaction. If every cell\n    ///         is taken the whole call reverts (`AllCellsTaken`) and\n    ///         nothing is charged. Painting the last empty cell ends the\n    ///         event.\n    /// @param referrer Optional: on the painter's FIRST-ever successful\n    ///        paint, a referrer other than the painter themselves is bound\n    ///        permanently, and every pixel this painter ever paints is\n    ///        credited to that referrer in the referral pool accounting.\n    ///        Later paints ignore the parameter.\n    function paint(Pixel[] calldata pixels, address referrer) external payable {\n        uint256 n = pixels.length;\n        if (n == 0 || n > PIXELS_PER_WINDOW) revert BadPixelCount();\n        if (startTime == 0 || block.timestamp >= endTime) revert EventNotActive();\n        // msg.sender on purpose: a relayer can't lend someone else's Agent ID\n        if (agentId.balanceOf(msg.sender) == 0) revert NoAgentId();\n        bool early = block.timestamp < publicTime;\n        uint256 price;\n        uint256 used;\n        if (early) {\n            if (!onWaitlist(msg.sender)) revert NotOnWaitlist();\n            price = WAITLIST_PRICE;\n            used = waitlistPixelsOf[msg.sender];\n        } else {\n            price = PUBLIC_PRICE;\n            used = publicPixelsOf[msg.sender];\n        }\n        if (msg.value != price * n) revert WrongPayment();\n        if (used + n > PIXELS_PER_WINDOW) revert NoPixelsLeft();\n\n        // Referral binding: first-ever paint only, never to oneself. The\n        // binding is written before the loop but only survives if at least\n        // one pixel is actually painted (a full revert undoes it).\n        address ref = referrerOf[msg.sender];\n        if (pixelsOf(msg.sender) == 0 && ref == address(0)) {\n            if (referrer != address(0) && referrer != msg.sender) {\n                ref = referrer;\n                referrerOf[msg.sender] = referrer;\n                emit ReferralBound(msg.sender, referrer);\n            }\n        }\n\n        uint256 painted;\n        for (uint256 i; i < n; ++i) {\n            Pixel calldata p = pixels[i];\n            if (p.x >= WIDTH || p.y >= HEIGHT) revert OutOfBounds();\n            if (p.color == 0 || p.color >= COLORS) revert InvalidColor();\n            uint256 idx = uint256(p.y) * WIDTH + uint256(p.x);\n            if (_getPixel(idx) != 0) {\n                // someone was faster (or the same cell twice): it stays theirs\n                emit CellTaken(msg.sender, p.x, p.y);\n                continue;\n            }\n            _setPixel(idx, p.color);\n            emit Painted(msg.sender, p.x, p.y, p.color);\n            ++painted;\n        }\n        if (painted == 0) revert AllCellsTaken();\n\n        if (pixelsOf(msg.sender) == 0) participants.push(msg.sender);\n        if (early) waitlistPixelsOf[msg.sender] = used + painted;\n        else publicPixelsOf[msg.sender] = used + painted;\n        if (ref != address(0)) {\n            referredPixelsOf[ref] += painted;\n            totalReferredPixels += painted;\n        }\n        if ((totalPixelsPainted += painted) == PIXELS) {\n            // no empty cell left: the picture is done, the event ends now\n            endTime = block.timestamp;\n            if (publicTime > block.timestamp) publicTime = block.timestamp;\n            emit CanvasFull(block.timestamp);\n        }\n\n        if (painted < n) {\n            (bool ok, ) = payable(msg.sender).call{value: price * (n - painted)}(\"\");\n            if (!ok) revert RefundFailed();\n        }\n    }\n\n    function _getPixel(uint256 idx) private view returns (uint256) {\n        return (_canvasSlots[idx >> 6] >> ((idx & 63) << 2)) & 0xF;\n    }\n\n    function _setPixel(uint256 idx, uint256 color) private {\n        uint256 slot = idx >> 6; // 64 pixels per slot\n        uint256 shift = (idx & 63) << 2; // 4 bits per pixel\n        _canvasSlots[slot] = (_canvasSlots[slot] & ~(uint256(0xF) << shift)) | (color << shift);\n    }\n\n    // ------------------------------------------------------------------\n    // Token generation\n    // ------------------------------------------------------------------\n\n    /// @notice Callable by anyone once the event has ended (canvas full or\n    ///         clock out). Freezes the canvas, opens the locked PancakeSwap\n    ///         V3 pool, pays the operator's BNB share and prepares the\n    ///         painters' and referral shares. Painters are paid by\n    ///         `distribute`, referrers by `claimReferral`.\n    function finalize() external {\n        if (startTime == 0 || block.timestamp < endTime) revert EventNotOver();\n        if (finalized) revert AlreadyFinalized();\n        finalized = true;\n\n        uint256 n = participants.length;\n        uint256 pixels = totalPixelsPainted;\n        canvasHash = keccak256(abi.encode(_canvasSlots));\n        uint256 revenue = address(this).balance;\n        uint256 lpTokens;\n        uint256 lpBnb;\n        uint256 operatorBnb;\n\n        if (pixels > 0) {\n            tokensPerPixel = PAINTER_SUPPLY / pixels;\n            // the rounding remainder of the painters' share goes to the pool,\n            // so exactly TOTAL_SUPPLY is minted across the lifecycle\n            lpTokens = LP_SUPPLY + (PAINTER_SUPPLY - tokensPerPixel * pixels);\n            uint256 referralMint;\n            if (totalReferredPixels > 0) {\n                tokensPerReferredPixel = REFERRAL_SUPPLY / totalReferredPixels;\n                referralMint = tokensPerReferredPixel * totalReferredPixels;\n                // the referral pool's rounding remainder goes to the pool too\n                lpTokens += REFERRAL_SUPPLY - referralMint;\n            } else {\n                // nobody referred anybody: the whole pool folds into LP\n                lpTokens += REFERRAL_SUPPLY;\n            }\n            lpBnb = (revenue * LP_BPS) / 10_000;\n            operatorBnb = revenue - lpBnb;\n\n            _seedLiquidity(lpBnb, lpTokens);\n            // ORDERING INVARIANT: the referral pool is minted to this\n            // contract only AFTER _seedLiquidity's dust sweep, so the sweep\n            // can never eat the pool.\n            if (referralMint > 0) token.mint(address(this), referralMint);\n            _sendBnb(operator, operatorBnb);\n        }\n\n        emit Finalized(canvasHash, n, pixels, tokensPerPixel, tokensPerReferredPixel, lpTokens, lpBnb, operatorBnb, positionId);\n    }\n\n    /// @dev Opens a full-range position in the ART/WBNB 0.25% pool at the\n    ///      price lpBnb / lpTokens, held by this contract for good.\n    ///      The pool can be created and initialized by anyone before this\n    ///      runs, and with no liquidity in it anyone can push its price\n    ///      anywhere for free. So the price is checked and, if needed, swapped\n    ///      back to the target first. Before finalize no ART exists, so\n    ///      the only liquidity an outsider can add is WBNB bids, which only\n    ///      stand in the way when the price has to come down, and then they\n    ///      buy our ART above the target price. That correction swap spends\n    ///      at most half of the pool's ART, so it can never leave the mint\n    ///      empty. (Shape and reasoning mirror Imprint's _seedLiquidity.)\n    function _seedLiquidity(uint256 lpBnb, uint256 lpTokens) private {\n        address art = address(token);\n        bool artIs0 = art < address(wbnb);\n        (address t0, address t1) = artIs0 ? (art, address(wbnb)) : (address(wbnb), art);\n        (uint256 a0, uint256 a1) = artIs0 ? (lpTokens, lpBnb) : (lpBnb, lpTokens);\n        // price = token1 / token0, as a Q64.96 square root\n        uint160 target = uint160(Math.sqrt(Math.mulDiv(a1, 1 << 192, a0)));\n\n        token.mint(address(this), lpTokens);\n        wbnb.deposit{value: lpBnb}();\n\n        address p = positionManager.createAndInitializePoolIfNecessary(t0, t1, POOL_FEE, target);\n        pool = p;\n        (uint160 current, , , , , , ) = IPancakeV3Pool(p).slot0();\n        if (current != target) {\n            bool zeroForOne = current > target; // price too high: sell token0\n            uint256 budget = (zeroForOne == artIs0) ? lpTokens / 2 : lpBnb / 2;\n            _swapPool = p;\n            IPancakeV3Pool(p).swap(address(this), zeroForOne, int256(budget), target, \"\");\n            _swapPool = address(0);\n        }\n\n        uint256 b0 = IERC20Lite(t0).balanceOf(address(this));\n        uint256 b1 = IERC20Lite(t1).balanceOf(address(this));\n        IERC20Lite(t0).approve(address(positionManager), b0);\n        IERC20Lite(t1).approve(address(positionManager), b1);\n        (positionId, , , ) = positionManager.mint(\n            IPositionManager.MintParams({\n                token0: t0,\n                token1: t1,\n                fee: POOL_FEE,\n                tickLower: TICK_LOWER,\n                tickUpper: TICK_UPPER,\n                amount0Desired: b0,\n                amount1Desired: b1,\n                amount0Min: 0,\n                amount1Min: 0,\n                recipient: address(this),\n                deadline: block.timestamp\n            })\n        );\n\n        // rounding dust: leftover ART is burned, leftover WBNB goes to the\n        // operator (as WBNB — the operator's BNB share already went by\n        // _sendBnb; this is swap dust only)\n        uint256 leftArt = IERC20Lite(art).balanceOf(address(this));\n        if (leftArt > 0) IERC20Lite(art).transfer(DEAD, leftArt);\n        uint256 leftWbnb = wbnb.balanceOf(address(this));\n        if (leftWbnb > 0) wbnb.transfer(operator, leftWbnb);\n    }\n\n    /// @dev Pays the price-correction swap in finalize(). Only the pool being\n    ///      corrected, and only during that swap, can call it.\n    function pancakeV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata) external {\n        address p = _swapPool;\n        if (p == address(0) || msg.sender != p) revert BadCallback();\n        (address art, address w) = (address(token), address(wbnb));\n        (address t0, address t1) = art < w ? (art, w) : (w, art);\n        if (amount0Delta > 0) IERC20Lite(t0).transfer(p, uint256(amount0Delta));\n        if (amount1Delta > 0) IERC20Lite(t1).transfer(p, uint256(amount1Delta));\n    }\n\n    /// @dev BNB to a wallet that can't take it is sent as WBNB instead, so a\n    ///      bad recipient can never block finalize().\n    function _sendBnb(address to, uint256 amount) private {\n        if (amount == 0) return;\n        (bool ok, ) = payable(to).call{value: amount}(\"\");\n        if (!ok) {\n            wbnb.deposit{value: amount}();\n            wbnb.transfer(to, amount);\n        }\n    }\n\n    /// @notice Mints each of the next `count` participants its pixels times\n    ///         `tokensPerPixel`, in join order. Anyone can call it until\n    ///         everyone has been paid.\n    function distribute(uint256 count) external {\n        if (!finalized) revert NotFinalized();\n        uint256 from = distributedCount;\n        uint256 n = participants.length;\n        if (from >= n || count == 0) revert NothingToDo();\n        uint256 to = from + count > n ? n : from + count;\n        distributedCount = to;\n        uint256 perPixel = tokensPerPixel;\n        for (uint256 i = from; i < to; i++) {\n            address a = participants[i];\n            token.mint(a, pixelsOf(a) * perPixel);\n        }\n        emit Distributed(from, to);\n    }\n\n    /// @notice Pulls the caller's referral-pool share:\n    ///         referredPixelsOf(me) * tokensPerReferredPixel. One claim ever.\n    ///         The tokens were minted to this contract at finalize().\n    function claimReferral() external {\n        if (!finalized) revert NotFinalized();\n        if (referralClaimed[msg.sender]) revert ReferralAlreadyClaimed();\n        uint256 amount = referredPixelsOf[msg.sender] * tokensPerReferredPixel;\n        if (amount == 0) revert NothingToClaim();\n        referralClaimed[msg.sender] = true;\n        token.transfer(msg.sender, amount);\n        emit ReferralClaimed(msg.sender, amount);\n    }\n\n    /// @notice Sends the trading fees earned by the locked pool position to\n    ///         the operator. Anyone can call it; the fees always go to\n    ///         `operator`. The liquidity itself never moves.\n    function collectFees() external returns (uint256 amount0, uint256 amount1) {\n        if (positionId == 0) revert NothingToDo();\n        (amount0, amount1) = positionManager.collect(\n            IPositionManager.CollectParams({\n                tokenId: positionId,\n                recipient: operator,\n                amount0Max: type(uint128).max,\n                amount1Max: type(uint128).max\n            })\n        );\n        emit FeesCollected(amount0, amount1);\n    }\n\n    /// @dev The position NFT is minted straight to this contract.\n    function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n\n    // ------------------------------------------------------------------\n    // Views\n    // ------------------------------------------------------------------\n\n    /// @notice The whole canvas as packed slots (4 bits per pixel, 64 per\n    ///         slot, index = y * WIDTH + x). The site renders from this.\n    function getCanvas() external view returns (uint256[] memory) {\n        return _canvasSlots;\n    }\n\n    function getPixel(uint16 x, uint16 y) external view returns (uint8) {\n        if (x >= WIDTH || y >= HEIGHT) revert OutOfBounds();\n        return uint8(_getPixel(uint256(y) * WIDTH + uint256(x)));\n    }\n\n    /// @notice Cells nobody has painted yet. 0 ends the event.\n    function emptyCells() external view returns (uint256) {\n        return PIXELS - totalPixelsPainted;\n    }\n\n    function pixelsOf(address who) public view returns (uint256) {\n        return waitlistPixelsOf[who] + publicPixelsOf[who];\n    }\n\n    function participantCount() external view returns (uint256) {\n        return participants.length;\n    }\n\n    function hasAgentId(address who) external view returns (bool) {\n        return agentId.balanceOf(who) > 0;\n    }\n\n    /// @notice Price of one pixel in the current window (the waitlist price\n    ///         before the event starts).\n    function paintPrice() public view returns (uint256) {\n        if (startTime != 0 && block.timestamp >= publicTime) return PUBLIC_PRICE;\n        return WAITLIST_PRICE;\n    }\n\n    function pixelsLeft(address who) public view returns (uint256) {\n        if (startTime == 0 || block.timestamp >= endTime) return 0;\n        if (block.timestamp < publicTime) return PIXELS_PER_WINDOW - waitlistPixelsOf[who];\n        return PIXELS_PER_WINDOW - publicPixelsOf[who];\n    }\n\n    function canPaint(address who) external view returns (bool) {\n        if (startTime == 0 || block.timestamp >= endTime) return false;\n        if (agentId.balanceOf(who) == 0) return false;\n        if (block.timestamp < publicTime && !onWaitlist(who)) return false;\n        return pixelsLeft(who) > 0;\n    }\n\n    /// @notice 0 = not started, 1 = waitlist window, 2 = public window,\n    ///         3 = ended, 4 = finalized.\n    function eventState() external view returns (uint8) {\n        if (finalized) return 4;\n        if (startTime == 0) return 0;\n        if (block.timestamp >= endTime) return 3;\n        if (block.timestamp < publicTime) return 1;\n        return 2;\n    }\n}\n\n/// @title ART canvas — production parameters (locked in SPEC.md).\n/// @notice Registry = Binance Agent ID `0x60B9...022F`, PancakeSwap V3\n///         position manager `0x46A1...4364` (WBNB read from it at\n///         construction). `operator` is the payout address for the 30% BNB\n///         share and pool fees; it receives no tokens.\ncontract ArtCanvas is ArtCanvasBase {\n    constructor(address agentId_, address positionManager_, address operator_)\n        ArtCanvasBase(\n            agentId_,\n            positionManager_,\n            operator_,\n            100, // WIDTH\n            100, // HEIGHT\n            5, // PIXELS_PER_WINDOW\n            0.001 ether, // WAITLIST_PRICE\n            0.0015 ether, // PUBLIC_PRICE\n            6 hours, // WAITLIST_DURATION\n            12 hours // DURATION\n        )\n    {}\n}\n"},"@openzeppelin/contracts/access/Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},"@openzeppelin/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n            // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2²⁵⁶ + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        uint256 exp;\n        unchecked {\n            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);\n            value >>= exp;\n            result += exp;\n\n            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);\n            value >>= exp;\n            result += exp;\n\n            result += SafeCast.toUint(value > 1);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        uint256 isGt;\n        unchecked {\n            isGt = SafeCast.toUint(value > (1 << 128) - 1);\n            value >>= isGt * 128;\n            result += isGt * 16;\n\n            isGt = SafeCast.toUint(value > (1 << 64) - 1);\n            value >>= isGt * 64;\n            result += isGt * 8;\n\n            isGt = SafeCast.toUint(value > (1 << 32) - 1);\n            value >>= isGt * 32;\n            result += isGt * 4;\n\n            isGt = SafeCast.toUint(value > (1 << 16) - 1);\n            value >>= isGt * 16;\n            result += isGt * 2;\n\n            result += SafeCast.toUint(value > (1 << 8) - 1);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},"@openzeppelin/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},"@openzeppelin/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"},"@openzeppelin/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"agentId_","type":"address","internalType":"address"},{"name":"positionManager_","type":"address","internalType":"address"},{"name":"operator_","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"AllCellsTaken","type":"error","inputs":[]},{"name":"AlreadyFinalized","type":"error","inputs":[]},{"name":"BadCallback","type":"error","inputs":[]},{"name":"BadPixelCount","type":"error","inputs":[]},{"name":"EventAlreadyStarted","type":"error","inputs":[]},{"name":"EventNotActive","type":"error","inputs":[]},{"name":"EventNotOver","type":"error","inputs":[]},{"name":"InvalidColor","type":"error","inputs":[]},{"name":"NoAgentId","type":"error","inputs":[]},{"name":"NoPixelsLeft","type":"error","inputs":[]},{"name":"NoToken","type":"error","inputs":[]},{"name":"NotFinalized","type":"error","inputs":[]},{"name":"NotOnWaitlist","type":"error","inputs":[]},{"name":"NothingToClaim","type":"error","inputs":[]},{"name":"NothingToDo","type":"error","inputs":[]},{"name":"OutOfBounds","type":"error","inputs":[]},{"name":"OwnableInvalidOwner","type":"error","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"name":"OwnableUnauthorizedAccount","type":"error","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"name":"ReferralAlreadyClaimed","type":"error","inputs":[]},{"name":"RefundFailed","type":"error","inputs":[]},{"name":"TokenAlreadySet","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[]},{"name":"CanvasFull","type":"event","inputs":[{"name":"time","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"CellTaken","type":"event","inputs":[{"name":"painter","type":"address","indexed":true,"internalType":"address"},{"name":"x","type":"uint16","indexed":false,"internalType":"uint16"},{"name":"y","type":"uint16","indexed":false,"internalType":"uint16"}],"anonymous":false},{"name":"Distributed","type":"event","inputs":[{"name":"fromIndex","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"toIndex","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"EventStarted","type":"event","inputs":[{"name":"publicTime","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"endTime","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"FeesCollected","type":"event","inputs":[{"name":"amount0","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"amount1","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"Finalized","type":"event","inputs":[{"name":"canvasHash","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"participants","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"pixels","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"tokensPerPixel","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"tokensPerReferredPixel","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"lpTokens","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"lpBnb","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"operatorBnb","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"positionId","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"OwnershipTransferred","type":"event","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"Painted","type":"event","inputs":[{"name":"painter","type":"address","indexed":true,"internalType":"address"},{"name":"x","type":"uint16","indexed":false,"internalType":"uint16"},{"name":"y","type":"uint16","indexed":false,"internalType":"uint16"},{"name":"color","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"name":"ReferralBound","type":"event","inputs":[{"name":"painter","type":"address","indexed":true,"internalType":"address"},{"name":"referrer","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"ReferralClaimed","type":"event","inputs":[{"name":"referrer","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"TokenSet","type":"event","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"name":"Waitlisted","type":"event","inputs":[{"name":"who","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"name":"COLORS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"DURATION","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"HEIGHT","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"LP_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"LP_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"OPERATOR_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PAINTER_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PIXELS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PIXELS_PER_WINDOW","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"POOL_FEE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint24","internalType":"uint24"}],"stateMutability":"view"},{"name":"PUBLIC_PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"REFERRAL_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"TICK_LOWER","type":"function","inputs":[],"outputs":[{"name":"","type":"int24","internalType":"int24"}],"stateMutability":"view"},{"name":"TICK_UPPER","type":"function","inputs":[],"outputs":[{"name":"","type":"int24","internalType":"int24"}],"stateMutability":"view"},{"name":"TOTAL_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"WAITLIST_DURATION","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"WAITLIST_PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"WIDTH","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"addToWaitlist","type":"function","inputs":[{"name":"who","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"agentId","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentIdRegistry"}],"stateMutability":"view"},{"name":"canPaint","type":"function","inputs":[{"name":"who","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"canvasHash","type":"function","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"name":"claimReferral","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"collectFees","type":"function","inputs":[],"outputs":[{"name":"amount0","type":"uint256","internalType":"uint256"},{"name":"amount1","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"distribute","type":"function","inputs":[{"name":"count","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"distributedCount","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"emptyCells","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"endTime","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"eventState","type":"function","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"finalize","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"finalized","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"getCanvas","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"name":"getPixel","type":"function","inputs":[{"name":"x","type":"uint16","internalType":"uint16"},{"name":"y","type":"uint16","internalType":"uint16"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"hasAgentId","type":"function","inputs":[{"name":"who","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"onERC721Received","type":"function","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"bytes4","internalType":"bytes4"}],"stateMutability":"pure"},{"name":"onWaitlist","type":"function","inputs":[{"name":"who","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"operator","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"paint","type":"function","inputs":[{"name":"pixels","type":"tuple[]","components":[{"name":"x","type":"uint16","internalType":"uint16"},{"name":"y","type":"uint16","internalType":"uint16"},{"name":"color","type":"uint8","internalType":"uint8"}],"internalType":"struct ArtCanvasBase.Pixel[]"},{"name":"referrer","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"payable"},{"name":"paintPrice","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"pancakeV3SwapCallback","type":"function","inputs":[{"name":"amount0Delta","type":"int256","internalType":"int256"},{"name":"amount1Delta","type":"int256","internalType":"int256"},{"name":"","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"participantCount","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"participants","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"pixelsLeft","type":"function","inputs":[{"name":"who","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"pixelsOf","type":"function","inputs":[{"name":"who","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"pool","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"positionId","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"positionManager","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IPositionManager"}],"stateMutability":"view"},{"name":"publicPixelsOf","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"publicTime","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"referralClaimed","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"referredPixelsOf","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"referrerOf","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"renounceOwnership","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"setToken","type":"function","inputs":[{"name":"token_","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"startEvent","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"startTime","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"token","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IArtToken"}],"stateMutability":"view"},{"name":"tokensPerPixel","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"tokensPerReferredPixel","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"totalPixelsPainted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"totalReferredPixels","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"transferOwnership","type":"function","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"waitlistCount","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"waitlistPixelsOf","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"wbnb","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IWBNB"}],"stateMutability":"view"}],"matchId":"59092098","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-11T07:45:33Z","match":"exact_match","chainId":"56","address":"0x3A56eb279C84C7D46177Da791967a212A3D3d3ed"}