{"sources":{"AgenticMinerSaleV2.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ninterface ISaleTokenV2 {\n    function minter() external view returns (address);\n    function mint(address to, uint256 amount) external;\n    function MAX_SUPPLY() external view returns (uint256);\n    function totalSupply() external view returns (uint256);\n}\n\ninterface IAgentRegistryV2 {\n    function balanceOf(address account) external view returns (uint256);\n}\n\n/// @title Agentic Miner — sale contract v2 (pot model + dynamic Mode B multiplier)\n/// @notice Agents holding a Binance `.ai` Agent ID mint shares at a fixed 0.002 BNB in two\n///         modes. Mode A: the deposit is held in this contract; after 24 hours the holder can\n///         claim the deposit back, plus a token reward, paid from this contract's pot. Mode B:\n///         the deposit is not refundable; it stays in the pot and forms the liquidity pool,\n///         which the team launches on PancakeSwap after the raise; its token reward —\n///         epoch base + epoch reserve component x the live multiplier, snapshotted at\n///         mint time — is claimable 14 days after the mint. The multiplier follows the\n///         classic formula: (shares minted this epoch + 1000) / (Mode B shares minted\n///         this epoch + 1000), in thousandths, capped at 5000 (5.000x); it is high while\n///         Mode B shares are scarce within the epoch and falls toward 1000 (1.000x) as\n///         they accumulate. Rewards halve every 150,000 network shares; minting ends at\n///         share #1,650,000. All BNB from both modes accumulates in this contract; the\n///         owner can withdraw the pot to the treasury address. Referrals raise the\n///         referrer's daily quotas permanently.\ncontract AgenticMinerSaleV2 is ReentrancyGuard {\n    uint256 public constant SHARE_PRICE = 0.002 ether;\n    uint256 public constant EPOCH_SHARES = 150_000;\n    uint256 public constant MAX_TOTAL_SHARES = 1_650_000;\n    uint256 public constant BASE_A = 280_000e18; // epoch-1 base reward per share (Mode A payout; also the base component of Mode B)\n    uint256 public constant BASE_RES_B = 315_000e18; // epoch-1 Mode B reserve component per share (multiplied)\n    uint256 public constant MULT_SEED = 1_000; // virtual shares on both sides of the multiplier ratio\n    uint256 public constant MULT_MAX = 5_000; // 5.000x, thousandths\n    uint256 public constant A_LOCK = 24 hours;\n    uint256 public constant B_LOCK = 14 days;\n    uint256 public constant BASE_QUOTA = 5; // per mode, per UTC day, before referral bonus\n    uint256 public constant MAX_CLAIM_IDS = 50;\n\n    ISaleTokenV2 public immutable token;\n    IAgentRegistryV2 public immutable registry;\n    address public immutable owner;\n    address public immutable treasury;\n\n    uint256 public totalShares;\n    uint256 public committed; // token rewards promised but not yet paid out\n    bool public mintPaused;\n\n    /// @notice Mode B shares minted within each epoch (0-based epoch index -> shares).\n    ///         Feeds the multiplier's denominator; Mode A shares never enter it.\n    mapping(uint256 => uint256) public epochBShares;\n\n    struct UserInfo {\n        uint64 firstDay; // UTC day number of first mint; 0 = never minted\n        address referrer;\n        uint32 refCount;\n        uint64 aDay;\n        uint32 aUsed;\n        uint64 bDay;\n        uint32 bUsed;\n        uint256 aCursor;\n    }\n\n    struct APosition {\n        uint256 shares;\n        uint256 reward;\n        uint64 unlockAt;\n        bool claimed;\n    }\n\n    struct BPosition {\n        uint256 shares;\n        uint256 reward;\n        uint64 start;\n        bool claimed;\n    }\n\n    mapping(address => UserInfo) public users;\n    mapping(address => APosition[]) public aPositions;\n    mapping(address => BPosition[]) public bPositions;\n\n    event MintModeA(address indexed user, uint256 positionId, uint256 shares, uint256 reward);\n    event MintModeB(address indexed user, uint256 positionId, uint256 shares, uint256 reward);\n    event ClaimRefund(address indexed user, uint256 bnbPaid, uint256 tokenPaid);\n    event ClaimReward(address indexed user, uint256 tokenPaid);\n    event ReferralBound(address indexed user, address indexed referrer);\n    event MintPausedSet(bool paused);\n    event Withdrawn(address indexed treasury, uint256 amount);\n\n    error NoAgentId();\n    error WrongValue();\n    error ZeroShares();\n    error QuotaExceeded(uint256 left);\n    error SoldOut(uint256 left);\n    error MintPaused();\n    error TooMany();\n    error BadPosition();\n    error NotOwner();\n    error TransferFailed();\n    error MinterMismatch();\n    error InsufficientPot(uint256 needed, uint256 available);\n    error ZeroAddress();\n\n    constructor(address token_, address registry_, address owner_, address treasury_) {\n        // The token must already exist and name this contract as its minter:\n        // a wrong address prediction fails loudly here instead of bricking.\n        if (ISaleTokenV2(token_).minter() != address(this)) revert MinterMismatch();\n        if (registry_ == address(0) || owner_ == address(0) || treasury_ == address(0)) {\n            revert ZeroAddress();\n        }\n        token = ISaleTokenV2(token_);\n        registry = IAgentRegistryV2(registry_);\n        owner = owner_;\n        treasury = treasury_;\n    }\n\n    // ------------------------------------------------------------ minting\n\n    /// @notice Mode A: deposit shares * 0.002 BNB. After 24 hours, claimRefund pays the\n    ///         deposit back plus the token reward, from this contract's pot.\n    function mintModeA(uint256 shares, address referrer) external payable nonReentrant {\n        _preMint(shares);\n        UserInfo storage u = users[msg.sender];\n        uint256 left = _aLeft(u);\n        if (shares > left) revert QuotaExceeded(left);\n        uint256 reward = _rewardA(shares);\n        _bindReferral(u, referrer);\n        _touchFirstDay(u);\n        u.aDay = _today();\n        u.aUsed += uint32(shares);\n        totalShares += shares;\n        committed += reward;\n        uint256 id = aPositions[msg.sender].length;\n        aPositions[msg.sender].push(\n            APosition({shares: shares, reward: reward, unlockAt: uint64(block.timestamp + A_LOCK), claimed: false})\n        );\n        emit MintModeA(msg.sender, id, shares, reward);\n    }\n\n    /// @notice Mode B: deposit shares * 0.002 BNB. The deposit is not refundable; it forms\n    ///         the liquidity pool. The token reward — epoch base + epoch reserve\n    ///         component x the multiplier in force at this moment — is snapshotted\n    ///         into the position and claimable after 14 days.\n    function mintModeB(uint256 shares, address referrer) external payable nonReentrant {\n        _preMint(shares);\n        UserInfo storage u = users[msg.sender];\n        uint256 left = _bLeft(u);\n        if (shares > left) revert QuotaExceeded(left);\n        uint256 reward = _rewardB(shares);\n        _bindReferral(u, referrer);\n        _touchFirstDay(u);\n        u.bDay = _today();\n        u.bUsed += uint32(shares);\n        _addEpochB(shares);\n        totalShares += shares;\n        committed += reward;\n        uint256 id = bPositions[msg.sender].length;\n        bPositions[msg.sender].push(\n            BPosition({shares: shares, reward: reward, start: uint64(block.timestamp), claimed: false})\n        );\n        emit MintModeB(msg.sender, id, shares, reward);\n    }\n\n    // ------------------------------------------------------------ claims\n\n    /// @notice Pays matured Mode A positions: the BNB deposit back plus the token reward,\n    ///         both from this contract. Empty ids = oldest first from the cursor (up to 50).\n    ///         Positions younger than 24 hours are skipped, never reverted. If the pot does\n    ///         not currently hold enough BNB for the deposits selected, the call reverts\n    ///         with InsufficientPot and nothing is claimed.\n    function claimRefund(uint256[] calldata ids) external nonReentrant {\n        APosition[] storage arr = aPositions[msg.sender];\n        uint256 n = arr.length;\n        uint256 bnbTotal = 0;\n        uint256 tokenTotal = 0;\n        uint256 claimCount = 0;\n        if (ids.length == 0) {\n            uint256 i = users[msg.sender].aCursor;\n            uint256 seen = 0;\n            while (i < n && seen < MAX_CLAIM_IDS) {\n                APosition storage p = arr[i];\n                if (!p.claimed) {\n                    seen++;\n                    if (block.timestamp >= p.unlockAt) {\n                        bnbTotal += p.shares * SHARE_PRICE;\n                        tokenTotal += p.reward;\n                        claimCount++;\n                    }\n                }\n                i++;\n            }\n        } else {\n            if (ids.length > MAX_CLAIM_IDS) revert TooMany();\n            for (uint256 k = 0; k < ids.length; k++) {\n                if (ids[k] >= n) revert BadPosition();\n                APosition storage p = arr[ids[k]];\n                if (!p.claimed && block.timestamp >= p.unlockAt) {\n                    bnbTotal += p.shares * SHARE_PRICE;\n                    tokenTotal += p.reward;\n                    claimCount++;\n                }\n            }\n        }\n        if (claimCount == 0) {\n            emit ClaimRefund(msg.sender, 0, 0);\n            return;\n        }\n        if (address(this).balance < bnbTotal) revert InsufficientPot(bnbTotal, address(this).balance);\n\n        // Mark first, then pay.\n        if (ids.length == 0) {\n            uint256 i = users[msg.sender].aCursor;\n            uint256 seen = 0;\n            while (i < n && seen < MAX_CLAIM_IDS) {\n                APosition storage p = arr[i];\n                if (!p.claimed) {\n                    seen++;\n                    if (block.timestamp >= p.unlockAt) p.claimed = true;\n                }\n                i++;\n            }\n            // The cursor only ever advances past CLAIMED positions, so a young\n            // position skipped today stays reachable tomorrow.\n            while (users[msg.sender].aCursor < n && arr[users[msg.sender].aCursor].claimed) {\n                users[msg.sender].aCursor++;\n            }\n        } else {\n            for (uint256 k = 0; k < ids.length; k++) {\n                APosition storage p = arr[ids[k]];\n                if (!p.claimed && block.timestamp >= p.unlockAt) p.claimed = true;\n            }\n        }\n        committed -= tokenTotal;\n        if (tokenTotal > 0) token.mint(msg.sender, tokenTotal);\n        if (bnbTotal > 0) {\n            (bool ok,) = msg.sender.call{value: bnbTotal}(\"\");\n            if (!ok) revert TransferFailed();\n        }\n        emit ClaimRefund(msg.sender, bnbTotal, tokenTotal);\n    }\n\n    /// @notice Pays the Mode B token reward for positions that are at least 14 days old.\n    ///         Empty ids = scan the caller's positions (up to 50 payouts per call).\n    ///         Young or already-claimed positions are skipped. Mode B deposits are\n    ///         never paid back by this function or any other.\n    function claimReward(uint256[] calldata ids) external nonReentrant {\n        BPosition[] storage arr = bPositions[msg.sender];\n        uint256 n = arr.length;\n        uint256 paid = 0;\n        if (ids.length == 0) {\n            uint256 done = 0;\n            for (uint256 i = 0; i < n && done < MAX_CLAIM_IDS; i++) {\n                BPosition storage p = arr[i];\n                if (!p.claimed && block.timestamp >= uint256(p.start) + B_LOCK) {\n                    p.claimed = true;\n                    paid += p.reward;\n                    done++;\n                }\n            }\n        } else {\n            if (ids.length > MAX_CLAIM_IDS) revert TooMany();\n            for (uint256 k = 0; k < ids.length; k++) {\n                if (ids[k] >= n) revert BadPosition();\n                BPosition storage p = arr[ids[k]];\n                if (!p.claimed && block.timestamp >= uint256(p.start) + B_LOCK) {\n                    p.claimed = true;\n                    paid += p.reward;\n                }\n            }\n        }\n        if (paid > 0) {\n            committed -= paid;\n            token.mint(msg.sender, paid);\n        }\n        emit ClaimReward(msg.sender, paid);\n    }\n\n    // ------------------------------------------------------------ owner\n\n    /// @notice Owner-only. Sends the contract's entire BNB balance (the pot: Mode A\n    ///         deposits not yet claimed back, plus all Mode B deposits) to the\n    ///         treasury address fixed in the constructor.\n    function withdraw() external nonReentrant {\n        if (msg.sender != owner) revert NotOwner();\n        uint256 amount = address(this).balance;\n        if (amount > 0) {\n            (bool ok,) = treasury.call{value: amount}(\"\");\n            if (!ok) revert TransferFailed();\n        }\n        emit Withdrawn(treasury, amount);\n    }\n\n    /// @notice Owner-only. Pauses or resumes minting. Claims are never paused.\n    function setMintPaused(bool paused_) external {\n        if (msg.sender != owner) revert NotOwner();\n        mintPaused = paused_;\n        emit MintPausedSet(paused_);\n    }\n\n    function paused() public view returns (bool) {\n        return mintPaused;\n    }\n\n    // ------------------------------------------------------------ views\n\n    struct Quota {\n        uint256 refCount;\n        uint256 aCap;\n        uint256 aUsed;\n        uint256 aLeft;\n        uint256 bCap;\n        uint256 bUsed;\n        uint256 bLeft;\n        uint256 stage;\n        uint256 aPerShare;\n        uint256 bRewardPerShare;\n        uint256 bMultiplier;\n        uint256 reserveLeft;\n        uint256 totalShares;\n        uint256 sharesLeftInStage;\n        uint256 sharesLeftTotal;\n        bool open;\n        bool paused;\n    }\n\n    /// @notice One call, 17 words — the full mint picture for any agent:\n    ///         0 refCount, 1 aCap, 2 aUsed, 3 aLeft, 4 bCap, 5 bUsed, 6 bLeft,\n    ///         7 stage (1-based epoch), 8 aPerShare, 9 bRewardPerShare (epoch\n    ///         base + epoch reserve component x the live multiplier, per share,\n    ///         reserve-pacing capped for the requested share count),\n    ///         10 bMultiplier (the live multiplier in thousandths: 1000 = 1.000x,\n    ///         up to 5000 = 5.000x), 11 reserveLeft, 12 totalShares,\n    ///         13 sharesLeftInStage, 14 sharesLeftTotal, 15 open (raise still\n    ///         running: not sold out), 16 paused. Returned as a tuple struct;\n    ///         the wire layout is identical to 17 plain return values.\n    function quota(address user, uint256 shares) external view returns (Quota memory q) {\n        UserInfo storage u = users[user];\n        q.refCount = u.refCount;\n        q.aCap = _cap(u);\n        q.aUsed = u.aDay == _today() ? u.aUsed : 0;\n        q.aLeft = q.aCap > q.aUsed ? q.aCap - q.aUsed : 0;\n        q.bCap = _cap(u);\n        q.bUsed = u.bDay == _today() ? u.bUsed : 0;\n        q.bLeft = q.bCap > q.bUsed ? q.bCap - q.bUsed : 0;\n        q.stage = _epochIndex() + 1;\n        q.aPerShare = _baseA(_epochIndex());\n        q.bRewardPerShare = _bPerShare(shares == 0 ? 1 : shares);\n        q.bMultiplier = _multiplier();\n        q.reserveLeft = _reserveLeft();\n        q.totalShares = totalShares;\n        q.sharesLeftInStage = (_epochIndex() + 1) * EPOCH_SHARES - totalShares;\n        if (q.sharesLeftInStage > EPOCH_SHARES) q.sharesLeftInStage = 0;\n        q.sharesLeftTotal = MAX_TOTAL_SHARES - totalShares;\n        q.open = totalShares < MAX_TOTAL_SHARES;\n        q.paused = mintPaused;\n    }\n\n    /// @notice 0 Mode A BNB claimable now (matured, unclaimed deposits),\n    ///         1 Mode A token claimable now, 2 Mode B token claimable now,\n    ///         3 Mode B positions claimable now. Mode A BNB claims are paid\n    ///         from the pot; if the pot is short at claim time the claim\n    ///         transaction reverts (see InsufficientPot).\n    function pending(address user)\n        external\n        view\n        returns (uint256 aBnbClaimable, uint256 aTokenClaimable, uint256 bTokenClaimable, uint256 bPositionsClaimable)\n    {\n        APosition[] storage arrA = aPositions[user];\n        for (uint256 i = 0; i < arrA.length; i++) {\n            if (!arrA[i].claimed && block.timestamp >= arrA[i].unlockAt) {\n                aBnbClaimable += arrA[i].shares * SHARE_PRICE;\n                aTokenClaimable += arrA[i].reward;\n            }\n        }\n        BPosition[] storage arrB = bPositions[user];\n        for (uint256 i = 0; i < arrB.length; i++) {\n            if (!arrB[i].claimed && block.timestamp >= uint256(arrB[i].start) + B_LOCK) {\n                bTokenClaimable += arrB[i].reward;\n                bPositionsClaimable++;\n            }\n        }\n    }\n\n    /// @notice Word 0 is firstDay (0 = never minted), as agent tooling expects.\n    function userInfo(address user)\n        external\n        view\n        returns (uint256 firstDay, address referrer, uint256 refCount, uint256 aPositionCount, uint256 bPositionCount)\n    {\n        UserInfo storage u = users[user];\n        return (u.firstDay, u.referrer, u.refCount, aPositions[user].length, bPositions[user].length);\n    }\n\n    // ------------------------------------------------------------ internals\n\n    function _preMint(uint256 shares) internal {\n        if (shares == 0) revert ZeroShares();\n        if (msg.value != shares * SHARE_PRICE) revert WrongValue();\n        if (registry.balanceOf(msg.sender) == 0) revert NoAgentId();\n        if (mintPaused) revert MintPaused();\n        if (totalShares >= MAX_TOTAL_SHARES) revert SoldOut(0);\n        if (totalShares + shares > MAX_TOTAL_SHARES) revert SoldOut(MAX_TOTAL_SHARES - totalShares);\n    }\n\n    function _bindReferral(UserInfo storage u, address referrer) internal {\n        if (u.firstDay != 0) return; // binding happens on the first mint only\n        if (\n            referrer != address(0) && referrer != msg.sender && registry.balanceOf(referrer) > 0\n                && users[referrer].firstDay != 0\n        ) {\n            u.referrer = referrer;\n            users[referrer].refCount += 1;\n            emit ReferralBound(msg.sender, referrer);\n        }\n    }\n\n    function _touchFirstDay(UserInfo storage u) internal {\n        if (u.firstDay == 0) u.firstDay = _today();\n    }\n\n    function _today() internal view returns (uint64) {\n        return uint64(block.timestamp / 1 days);\n    }\n\n    function _cap(UserInfo storage u) internal view returns (uint256) {\n        return BASE_QUOTA + u.refCount;\n    }\n\n    function _aLeft(UserInfo storage u) internal view returns (uint256) {\n        uint256 used = u.aDay == _today() ? u.aUsed : 0;\n        uint256 cap = _cap(u);\n        return cap > used ? cap - used : 0;\n    }\n\n    function _bLeft(UserInfo storage u) internal view returns (uint256) {\n        uint256 used = u.bDay == _today() ? u.bUsed : 0;\n        uint256 cap = _cap(u);\n        return cap > used ? cap - used : 0;\n    }\n\n    function _epochIndex() internal view returns (uint256) {\n        uint256 e = totalShares / EPOCH_SHARES;\n        return e > 10 ? 10 : e;\n    }\n\n    function _epochIndexAt(uint256 sharesCount) internal pure returns (uint256) {\n        uint256 e = sharesCount / EPOCH_SHARES;\n        return e > 10 ? 10 : e;\n    }\n\n    function _baseA(uint256 epoch) internal pure returns (uint256) {\n        return BASE_A >> epoch;\n    }\n\n    function _baseResB(uint256 epoch) internal pure returns (uint256) {\n        return BASE_RES_B >> epoch;\n    }\n\n    function _reserveLeft() internal view returns (uint256) {\n        uint256 capLeft = token.MAX_SUPPLY() - token.totalSupply();\n        return capLeft > committed ? capLeft - committed : 0;\n    }\n\n    /// @dev The live Mode B multiplier, in thousandths: (shares minted in the\n    ///      current epoch + the 1000-share virtual buffer) / (Mode B shares\n    ///      minted in the current epoch + the same buffer), capped at 5000\n    ///      (5.000x). Because Mode B shares are a subset of the epoch's total\n    ///      shares, the ratio never falls below 1000 (1.000x); the explicit\n    ///      floor clamp below is a no-op safeguard.\n    function _multiplier() internal view returns (uint256 mult) {\n        uint256 epoch = _epochIndex();\n        uint256 epochShares = totalShares - epoch * EPOCH_SHARES;\n        mult = (epochShares + MULT_SEED) * 1_000 / (epochBShares[epoch] + MULT_SEED);\n        if (mult > MULT_MAX) mult = MULT_MAX;\n        if (mult < 1_000) mult = 1_000;\n    }\n\n    /// @dev Mode B reward per share at the live multiplier, for a prospective\n    ///      mint: epoch base + epoch reserve component x multiplier / 1000,\n    ///      with the reserve pacing cap (a mint never promises more than the\n    ///      reserve left).\n    function _bPerShare(uint256 shares) internal view returns (uint256) {\n        uint256 epoch = _epochIndex();\n        uint256 perShare = _baseA(epoch) + _baseResB(epoch) * _multiplier() / 1_000;\n        uint256 reserve = _reserveLeft();\n        if (perShare * shares > reserve) perShare = reserve / shares;\n        return perShare;\n    }\n\n    /// @dev Splits a Mode A mint across epoch boundaries, summing per-share\n    ///      rewards, and caps the total at the remaining reward reserve.\n    function _rewardA(uint256 shares) internal view returns (uint256 reward) {\n        uint256 remaining = shares;\n        uint256 cursor = totalShares;\n        while (remaining > 0) {\n            uint256 epoch = _epochIndexAt(cursor);\n            uint256 inEpoch = (epoch + 1) * EPOCH_SHARES - cursor;\n            uint256 take = remaining < inEpoch ? remaining : inEpoch;\n            reward += take * _baseA(epoch);\n            cursor += take;\n            remaining -= take;\n        }\n        uint256 reserve = _reserveLeft();\n        return reward > reserve ? reserve : reward;\n    }\n\n    /// @dev Mode B reward: the multiplier is snapshotted once, at mint entry,\n    ///      and applied to every epoch segment of the mint; each segment prices\n    ///      its (halved) base + reserve component at that snapshot. The total\n    ///      is capped at the remaining reward reserve (pacing).\n    function _rewardB(uint256 shares) internal view returns (uint256 reward) {\n        uint256 mult = _multiplier();\n        uint256 remaining = shares;\n        uint256 cursor = totalShares;\n        while (remaining > 0) {\n            uint256 epoch = _epochIndexAt(cursor);\n            uint256 inEpoch = (epoch + 1) * EPOCH_SHARES - cursor;\n            uint256 take = remaining < inEpoch ? remaining : inEpoch;\n            reward += take * (_baseA(epoch) + _baseResB(epoch) * mult / 1_000);\n            cursor += take;\n            remaining -= take;\n        }\n        uint256 reserve = _reserveLeft();\n        return reward > reserve ? reserve : reward;\n    }\n\n    /// @dev Records a Mode B mint's shares against the epoch(s) they land in,\n    ///      splitting at epoch boundaries. Must be called with the pre-mint\n    ///      totalShares as the cursor base.\n    function _addEpochB(uint256 shares) internal {\n        uint256 remaining = shares;\n        uint256 cursor = totalShares;\n        while (remaining > 0) {\n            uint256 epoch = _epochIndexAt(cursor);\n            uint256 inEpoch = (epoch + 1) * EPOCH_SHARES - cursor;\n            uint256 take = remaining < inEpoch ? remaining : inEpoch;\n            epochBShares[epoch] += take;\n            cursor += take;\n            remaining -= take;\n        }\n    }\n\n    /// @notice Plain BNB transfers are accepted and simply join the pot; they\n    ///         are not a mint and buy nothing.\n    receive() external payable {}\n}\n"},"@openzeppelin/contracts/utils/ReentrancyGuard.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n"}},"matchId":"58783685","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-07T20:35:27Z","match":"exact_match","chainId":"56","address":"0x9f45F04A8D6718671cfbeF2740A4eF40cb3337e2"}