Farseen0/scar-pairs huggingface dataset:
MEDIUM severity: The `wpowi` function in the `LibMathSigned` library is responsible for calculating the Wad value `x`. The `wpowi` function in the `LibMathSigned` library is responsible for calculating the Wad value `x` raised to the power of `n`. The exponent `n` is declared as a signed integer, which is a common practice in many mathematical operations. However, the function's behavior is incorrect when calculatin...

Vulnerable code:
```\nfunction wpowi(int256 x, int256 n) internal pure returns (int256 z) {\n    z = n % 2!= 0? x : _WAD;\n\n    for (n /= 2; n!= 0; n /= 2) {\n        x = wmul(x, x);\n\n        if (n % 2!= 0) {\n            z = wmul(z, x);\n        }\n    }\n}\n```
MEDIUM severity: The vulnerability allows a malicious user to manipulate the premium emissions in their favor by cont. The vulnerability allows a malicious user to manipulate the premium emissions in their favor by controlling the perpetual maker TWAP and the oracle TWAP. This is achieved by calculating the premium for a position based on the difference between the perpetual maker TWAP and the oracle TWAP, which is...

Vulnerable code:
```\nint256 premium = getMarkPriceTwap() - underlyingPrice;\n```\n```\nuint256 currentPeriodStart = (_blockTimestamp() / spotPriceTwapInterval) * spotPriceTwapInterval;\nuint256 lastPeriodStart = currentPeriodStart - spotPriceTwapInterval;\n\nif (markPriceTwapData.lastTimestamp <= lastPeriodStart) {\n    return markPriceTwapData.lastPrice;\n}\n\nif (markPriceTwapData.lastTimestamp >= currentPeriodStart) {\n    twap = markPriceTwapData.lastPeriodAccumulator / spotPriceTwapInterval;\n} else {\n    uint256 currentAccumulator = markPriceTwapData.accumulator + (currentPeriodStart - markPriceTwapData.lastTimestamp) * markPriceTwapData.lastPrice;\n    twap = currentAccumulator / spotPriceTwapInterval;\n}\n```\n```\ndiff --git a/hubble-protocol/test/foundry/OrderBook.t.sol b/hubble-protocol/test/foundry/OrderBook.t.sol\nindex b4dafdf..f5d36b2 100644\n--- a/hubble-protocol/test/foundry/OrderBook.t.sol\n@@ -228,6 +228,60 @@\ncontract OrderBookTests is Utils {\n    function testUserCanControlEmissions() public {\n        uint256 price = 1e6;\n        oracle.setUnderlyingPrice(address(wavax), int(uint(price)));\n\n        uint256 marginRequired = orderBook.getRequiredMargin(100 * MIN_SIZE, price) * 1e18 / uint(defaultWethPrice) * 1e10; // required weth margin in 1e18, add 1e10 for any precision loss\n\n        addMargin(alice, marginRequired, 1, address(weth));\n        addMargin(bob, marginRequired, 1, address(weth));\n\n        placeAndExecuteOrder(0, aliceKey, bobKey, MIN_SIZE * 90, price, true, false, MIN_SIZE * 90, false);\n\n        int256 availableMargin = marginAccount.getAvailableMargin(alice);\n        assertApproxEqRel(availableMargin, 200410, 0.1e18); // Assert within 10%\n\n        uint256 spreadLimit = amm.maxOracleSpreadRatio();\n        uint minPrice = price * (1e6 - spreadLimit) / 1e6;\n\n        for (uint i = 0; i < 100; i++) {\n            uint256 currentPeriodStart = (block.timestamp / 1 hours) * 1 hours;\n            vm.warp(currentPeriodStart + 3590);\n\n            placeAndExecuteOrder(0, aliceKey, aliceKey, MIN_SIZE, minPrice, true, false, MIN_SIZE, false);\n\n            vm.warp(currentPeriodStart + (3600 * 2) + 10);\n\n            orderBook.settleFunding();\n        }\n\n        availableMargin = marginAccount.getAvailableMargin(alice);\n        assertApproxEqRel(availableMargin, 716442910, 0.1e18); // Assert within 10%\n    }\n\n    function testLiquidateAndExecuteOrder(uint64 price, uint120 size_) public {\n        vm.assume(price > 10 && size_!= 0);\n        oracle.setUnderlyingPrice(address(wavax), int(uint(price)));\n```
MEDIUM severity: The `IComptroller.exitMarket` and `IComptroller.enterMarkets` functions may return a non-zero uint v. The `IComptroller.exitMarket` and `IComptroller.enterMarkets` functions may return a non-zero uint value to indicate an error condition, but none of the Providers in the codebase check for this return value. This could potentially lead to unexpected behavior or errors being silently ignored.\n\nIn t...

Vulnerable code:
```\nif (amountOwed!= 0) {\n    return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n}\n\nif (allowed!= 0) {\n    return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n}\n```\n```\n/**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow.\n * @param cTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\nfunction exitMarket(address cTokenAddress) external returns (uint) {\n    CToken cToken = CToken(cTokenAddress);\n\n    // Get sender tokensHeld and amountOwed underlying from the cToken\n    (uint oErr, uint tokensHeld, uint amountOwed, ) = cToken.getAccountSnapshot(msg.sender);\n    require(oErr == 0, "exitMarket: getAccountSnapshot failed"); // semi-opaque error code\n\n    // Fail if the sender has a borrow balance\n    if (amountOwed!= 0) {\n        return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n    }\n\n    // Fail if the sender is not permitted to redeem all of their tokens\n    uint allowed = redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\n    if (allowed!= 0) {\n        return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n    }\n```\n```\nfunction _exitCollatMarket(address _cyTokenAddress) internal {\n    IComptroller comptroller = IComptroller(_getComptrollerAddress());\n    comptroller.exitMarket(_cyTokenAddress);\n}\n```\n```\nfunction _exitCollatMarket(address _cyTokenAddress) internal {\n    IComptroller comptroller = IComptroller(_getComptrollerAddress());\n    comptroller.exitMarket(_cyTokenAddress);\n}\n```\n```\nfunction _exitCollatMarket(address _cTokenAddress) internal {\n    IComptroller comptroller = IComptroller(_getComptrollerAddress());\n    comptroller.exitMarket(_cTokenAddress);\n}\n```\n```\nfunction _exitCollatMarket(address _cyTokenAddress) internal {\n    IComptroller comptroller = IComptroller(_getComptrollerAddress());\n    comptroller.exitMarket(_cyTokenAddress);\n}\n```\n```\nfunction _enterCollatMarket(address _cyTokenAddress) internal {\n    IComptroller comptroller = IComptroller(_getComptrollerAddress());\n\n    address[] memory cyTokenMarkets = new address[](1);\n    cyTokenMarkets[0] = _cyTokenAddress;\n    comptroller.enterMarkets(cyTokenMarkets);\n}\n```
MEDIUM severity: The `finishLiquidation()` function in the D3VaultLiquidation contract is susceptible to precision lo. The `finishLiquidation()` function in the D3VaultLiquidation contract is susceptible to precision loss when calculating the `realDebt` variable. This occurs due to the division operation being performed before multiplication, which can lead to the loss of significant figures.\n\nThe calculation of `...

Vulnerable code:
```\nuint256 realDebt = \n    borrows.div(record.interestIndex == 0? 1e18 : record.interestIndex).mul(info.borrowIndex);\n```\n```\ninfo.totalBorrows = info.totalBorrows - realDebt\n```
MEDIUM severity: The vulnerability arises when attempting to claim assets from the vault, specifically in situations . The vulnerability arises when attempting to claim assets from the vault, specifically in situations where the market position allocation calculations involve double subtraction of the claimed assets. This occurs when the `Vault.update` function rebalances collateral by calling `_manage`, which calcu...

Vulnerable code:
```\n_manage(context, depositAssets, claimAmount, \n   !depositAssets.isZero() ||!redeemShares.isZero())\n```\n```\nUFixed6 collateral = UFixed6Lib.unsafeFrom(strategy.totalCollateral).add(deposit).unsafeSub(withdrawal);\nUFixed6 assets = collateral.unsafeSub(ineligible);\n\nif (collateral.lt(strategy.totalMargin)) {\n    revert StrategyLibInsufficientCollateralError();\n}\n\nif (assets.lt(strategy.minAssets)) {\n    revert StrategyLibInsufficientAssetsError();\n}\n```\n```\nfunction _ineligable(Context memory context, UFixed6 withdrawal) private pure returns (UFixed6) {\n    UFixed6 redemptionEligable = UFixed6Lib.unsafeFrom(context.totalCollateral)\n       .unsafeSub(withdrawal)\n       .unsafeSub(context.global.assets)\n       .unsafeSub(context.global.deposit);\n\n    return redemptionEligable\n       .mul(context.global.redemption.unsafeDiv(context.global.shares.add(context.global.redemption)))\n       .add(context.global.assets)\n       .add(withdrawal);\n}\n```\n```\nif (assets.lt(strategy.minAssets)) {\n    revert StrategyLibInsufficientAssetsError();\n}\n```\n```\nit('simple deposits and redemptions', async () => {\n  // Now we should have opened positions.\n  // The positions should be equal to (smallDeposit + largeDeposit) * leverage originalOraclePrice.\n  expect(await position()).to.equal(\n    smallDeposit.add(largeDeposit).mul(leverage).mul(4).div(5).div(originalOraclePrice),\n  );\n  expect(await btcPosition()).to.equal(\n    smallDeposit.add(largeDeposit).mul(leverage).div(5).div(btcOriginalOraclePrice),\n  );\n\n  var half = smallDeposit.add(largeDeposit).div(2).add(smallDeposit);\n  await vault.connect(user).update(user.address, 0, half, 0);\n  await updateOracle();\n  await vault.connect(user2).update(user2.address, smallDeposit, 0, 0); // this will create min position in the market\n  await vault.connect(user).update(user.address, 0, 0, half); // this will revert even though it's just claiming\n})\n```
MEDIUM severity: The CouncilMember contract is vulnerable to a critical issue that renders the contract inoperable af. The CouncilMember contract is vulnerable to a critical issue that renders the contract inoperable after the first execution of the `burn` function. This vulnerability arises from the incorrect management of the `balances` array, which is shortened by one each time an ERC721 token is burned. The late...

Vulnerable code:
```\nfunction burn(\n    // rest of code\n    balances.pop(); // FOUND: balances.length decreases, while latest minted NFT withholds its unique tokenId\n    _burn(tokenId);\n)\n```\n```\nfunction mint(\n    // rest of code\n    balances.push(0);\n    _mint(newMember, totalSupply());\n```\n```\ndiff --git a/telcoin-audit/test/sablier/CouncilMember.test.ts b/telcoin-audit/test/sablier/CouncilMember.test.ts\nindex 675b89d..ab96b08 100644\n--- a/telcoin-audit/test/sablier/CouncilMember.test.ts\n+++ b/telcoin-audit/test/sablier/CouncilMember.test.ts\n@@ -1,13 +1,14 @@\nimport { expect } from "chai";\nimport { ethers } from "hardhat";\nimport { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";\nimport { CouncilMember, TestTelcoin, TestStream, ERC721Upgradeable__factory } from "../../typechain-types";\n\ndescribe("CouncilMember", () => {\n    let admin: SignerWithAddress;\n    let support: SignerWithAddress;\n    let member: SignerWithAddress;\n    let holder: SignerWithAddress;\n    let lastCouncilMember: SignerWithAddress;\n    let councilMember: CouncilMember;\n    let telcoin: TestTelcoin;\n    let stream: TestStream;\n\n    describe("CouncilMember", () => {\n        let supportRole: string = ethers.keccak256(ethers.toUtf8Bytes("SUPPORT_ROLE"));\n\n        beforeEach(async () => {\n            [admin, support, member, holder, lastCouncilMember] = await ethers.getSigners();\n\n            const TestTelcoinFactory = await ethers.getContractFactory("TestTelcoin", admin);\n            telcoin = await TestTelcoinFactory.deploy(admin.address);\n\n            councilMember = await CouncilMember.deploy(admin.address, support.address, telcoin.address);\n        });\n\n        it("the correct removal is made", async () => {\n            await expect(councilMember.burn(1, support.address)).emit(councilMember, "Transfer");\n        });\n\n        it.only("inoperable contract after burn", async () => {\n            await expect(councilMember.mint(lastCouncilMember.address)).to.not.reverted;\n\n            // This 1st burn will cause contract inoperable due to tokenId & balances misalignment\n            await expect(councilMember.burn(1, support.address)).emit(councilMember, "Transfer");\n\n            // Impact 1. holder with tokenId > balances length cannot claim\n            await expect(councilMember.connect(lastCouncilMember).claim(3, 1)).to.revertedWithPanic("0x32");\n\n            // Impact 2. subsequent\n```
MEDIUM severity: The `decreaseCollateral` and `increaseCollateral` functions in the `ShortRecordFacet` contract calcu. The `decreaseCollateral` and `increaseCollateral` functions in the `ShortRecordFacet` contract calculate the short's collateral ratio based on the cached asset price, which may be outdated, leading to a divergence between the actual collateral ratio (based on the asset spot price) and the calculated...

Vulnerable code:
```\nfunction decreaseCollateral(address asset, uint8 id, uint256 amount)\n    external\n    isNotFrozen(asset)\n    nonReentrant\n    onlyValidShortRecord(asset, msg.sender, id)\n{\n    STypes.ShortRecord storage short = s.shortRecords[asset][msg.sender][id];\n    short.updateErcDebt(asset);\n    if (amount > short.collateral) {\n        revert Errors.InsufficientCollateral();\n    }\n    short.collateral -= amount;\n\n    uint256 cRatio = short.getCollateralRatio(asset);\n    if (cRatio < LibAsset.initialMargin(asset)) {\n        revert Errors.CollateralLowerThanMin();\n    }\n    uint256 vault = s.asset[asset].vault;\n    s.vaultUser[vault][msg.sender].ethEscrowed += amount;\n    LibShortRecord.disburseCollateral(\n        asset, msg.sender, amount, short.zethYieldRate, short.updatedAt\n    );\n    emit Events.DecreaseCollateral(asset, msg.sender, id, amount);\n}\n```\n```\nfunction getCollateralRatio(\n    STypes.ShortRecord memory short,\n    address asset\n) \ninternal\nview\nreturns (uint256 cRatio) {\n    return short.collateral.div(short.ercDebt.mul(LibOracle.getPrice(asset)));\n}\n```\n```\nfunction getPrice(address asset) internal view returns (uint80 oraclePrice) {\n    AppStorage storage s = appStorage();\n    return uint80(s.bids[asset][Constants.HEAD].ercAmount);\n}\n```
MEDIUM severity: The `LyraPositionHandlerL2` contract's `onlyAuthorized` modifier, which is applied to several functi. The `LyraPositionHandlerL2` contract's `onlyAuthorized` modifier, which is applied to several functions, allows either the L2 keeper or the L1 `LyraPositionHandler` to execute these functions via the `L2CrossDomainMessenger`. This implementation is problematic because it unnecessarily expands the li...

Vulnerable code:
```\nmodifier onlyAuthorized() {\n    require(\n        (msg.sender == L2CrossDomainMessenger &&\n            OptimismL2Wrapper.messageSender() == positionHandlerL1) ||\n        msg.sender == keeper,\n        "ONLY_AUTHORIZED"\n    );\n}\n```\n```\nfunction closePosition(bool toSettle) public override onlyAuthorized {\n    LyraController._closePosition(toSettle);\n    UniswapV3Controller._estimateAndSwap(\n        false,\n        LyraController.sUSD.balanceOf(address(this))\n    );\n}\n\n// MAINTENANCE FUNCTIONS\n\n/// @notice Sweep tokens\n/// @param _token Address of the token to sweep\nfunction sweep(address _token) public override onlyAuthorized {\n    IERC20(_token).transfer(\n        msg.sender,\n        IERC20(_token).balanceOf(address(this))\n    );\n}\n\n/// @notice socket registry setter\n/// @param _socketRegistry new address of socket registry\nfunction setSocketRegistry(address _socketRegistry) public onlyAuthorized {\n    socketRegistry = _socketRegistry;\n}\n\n/// @notice keeper setter\n/// @param _keeper new keeper address\nfunction setKeeper(address _keeper) public onlyAuthorized {\n    keeper = _keeper;\n}\n```
MEDIUM severity: The bitcoin-spv library is vulnerable to multiple integer underflows and overflows while processing . The bitcoin-spv library is vulnerable to multiple integer underflows and overflows while processing or converting potentially untrusted or user-provided data. This vulnerability can occur in various functions within the library, including those responsible for extracting and processing data from inp...

Vulnerable code:
```\nfunction extractTarget(bytes memory _header) internal pure returns (uint256) {\n    bytes memory _m = _header.slice(72, 3);\n    uint8 _e = uint8(_header[75]);\n    uint256 _mantissa = bytesToUint(reverseEndianness(_m));\n    uint _exponent = _e - 3;\n\n    return _mantissa * (256 ** _exponent);\n}\n```\n```\nfunction determineOutputLength(bytes memory _output) internal pure returns (uint256) {\n    uint8 _len = uint8(_output.slice(8, 1)[0]);\n    require(_len < 0xfd, "Multi-byte VarInts not supported");\n\n    return _len + 8 + 1; // 8 byte value, 1 byte for _len itself\n}\n```\n```\nfunction extractHash(bytes memory _output) internal pure returns (bytes memory) {\n    if (uint8(_output.slice(9, 1)[0]) == 0) {\n        uint256 _len = uint8(extractOutputScriptLen(_output)[0]) - 2;\n        if (uint8(_output.slice(10, 1)[0])!= uint8(_len)) {\n            return bytes32("");\n        }\n        return _output.slice(11, _len);\n    } else {\n        bytes32 _tag = _output.keccak256Slice(8, 3);\n    }\n}\n```\n```\nfunction slice(bytes memory _bytes, uint _start, uint _length) internal pure returns (bytes memory res) {\n    require(_bytes.length >= (_start + _length), "Slice out of bounds");\n}\n```\n```\nfunction toUint(bytes memory _bytes, uint _start) internal pure returns (uint256) {\n    require(_bytes.length >= (_start + 32), "Uint conversion out of bounds.");\n}\n```\n```\nfunction toAddress(bytes memory _bytes, uint _start) internal pure returns (address) {\n    require(_bytes.length >= (_start + 20), "Address conversion out of bounds.");\n}\n```\n```\nfunction slice(bytes memory _bytes, uint _start, uint _length) internal pure returns (bytes memory res) {\n    require(_bytes.length >= (_start + _length), "Slice out of bounds");\n}\n```\n```\nfunction keccak256Slice(bytes memory _bytes, uint _start, uint _length) pure internal returns (bytes32 result) {\n    require(_bytes.length >= (_start + _length), "Slice out of bounds");\n}\n```
MEDIUM severity: The `curate()` function in the `Axis-Finance` protocol is responsible for setting a curator fee for . The `curate()` function in the `Axis-Finance` protocol is responsible for setting a curator fee for an auction. The fee is calculated as a percentage of the auction's funding, which is stored in the `funding` variable of the `Routing` struct. The `funding` variable is of type `uint96`, which has a m...

Vulnerable code:
```\nstruct Routing {\n    uint96 funding;\n}\n```\n```\nunchecked {\n    routing.funding += curatorFeePayout;\n}\n```\n```\nfunction test_CuratorFeeOverflow() public {\n    vm.startPrank(alice);\n\n    Veecode veecode = fixedPriceAuctionModule.VEECODE();\n    Keycode keycode = keycodeFromVeecode(veecode);\n\n    bytes memory _derivativeParams = "";\n\n    uint96 lotCapacity = 75_000_000_000e18; // this is 75 billion tokens\n    mockBaseToken.mint(alice, 100_000_000_000e18);\n    mockBaseToken.approve(address(auctionHouse), type(uint256).max);\n\n    FixedPriceAuctionModule.FixedPriceParams memory myStruct = FixedPriceAuctionModule.FixedPriceParams({\n        price: uint96(1e18),\n        maxPayoutPercent: uint24(1e5)\n    });\n\n    Auctioneer.RoutingParams memory routingA = Auctioneer.RoutingParams({\n        auctionType: keycode,\n        baseToken: mockBaseToken,\n        quoteToken: mockQuoteToken,\n        curator: curator,\n        callbacks: ICallback(address(0)),\n        callbackData: abi.encode(""),\n        derivativeType: toKeycode(""),\n        derivativeParams: _derivativeParams,\n        wrapDerivative: false,\n        prefunded: true\n    });\n\n    Auction.AuctionParams memory paramsA = Auction.AuctionParams({\n        start: 0,\n        duration: 1 days,\n        capacityInQuote: false,\n        capacity: lotCapacity,\n        implParams: abi.encode(myStruct)\n    });\n\n    string memory infoHashA;\n    auctionHouse.auction(routingA, paramsA, infoHashA);\n\n    vm.stopPrank();\n\n    vm.startPrank(owner);\n    FeeManager.FeeType type_ = FeeManager.FeeType.MaxCurator;\n    uint48 fee = 7_500; // 7.5% max curator fee\n    auctionHouse.setFee(keycode, type_, fee);\n    vm.stopPrank();\n\n    vm.startPrank(curator);\n    uint96 fundingBeforeCuratorFee;\n    uint96 fundingAfterCuratorFee;\n    (, fundingBeforeCuratorFee,,,,,,,) = auctionHouse.lotRouting(0);\n    console2.log("Here is the funding normalized before curator fee is set: ", fundingBeforeCuratorFee / 1e18);\n    auctionHouse.setCuratorFee(keycode, fee);\n    bytes memory callbackData_ = "";\n    auctionHouse.curate(0, callbackData_);\n    (, funding\n```\n```\nLogs:\n    Here is the funding normalized before curator fee is set: 75000000000\n    Here is the funding normalized after curator fee is set: 1396837485\n    Balance of base token of the auction house: 80625000000\n```
MEDIUM severity: The `MultipleWinners` strategy exhibits inconsistent behavior compared to `SingleRandomWinner` when . The `MultipleWinners` strategy exhibits inconsistent behavior compared to `SingleRandomWinner` when encountering an error condition during the drawing process. Specifically, `MultipleWinners` attempts to distribute awards even when `ticket.draw()` returns `address(0)`, which indicates an error. This...

Vulnerable code:
```\ncontract SingleRandomWinner is PeriodicPrizeStrategy {\n    function _distribute(uint256 randomNumber) internal override {\n        uint256 prize = prizePool.captureAwardBalance();\n        address winner = ticket.draw(randomNumber);\n        if (winner!= address(0)) {\n            _awardTickets(winner, prize);\n            _awardAllExternalTokens(winner);\n        }\n    }\n}\n```\n```\nfunction _distribute(uint256 randomNumber) internal override {\n    uint256 prize = prizePool.captureAwardBalance();\n\n    // main winner gets all external tokens\n    address mainWinner = ticket.draw(randomNumber);\n    _awardAllExternalTokens(mainWinner);\n\n    address[] memory winners = new address[](_numberOfWinners);\n    winners[0] = mainWinner;\n```
MEDIUM severity: This vulnerability occurs when a comparison operator (`==`) is used instead of an assignment operato. This vulnerability occurs when a comparison operator (`==`) is used instead of an assignment operator (`=`) in a code block. Specifically, the code snippet in question is attempting to update the value of `self._validators[_pk].state`, but is instead performing a comparison operation.\n\nThe code bl...

Vulnerable code:
```\nself._validators[_pk].state == 2\n```\n```\nself._validators[_pk].state == 3\n```
MEDIUM severity: The Hats contract, which inherits from the ERC1155 contract, fails to override the `balanceOfBatch` . The Hats contract, which inherits from the ERC1155 contract, fails to override the `balanceOfBatch` function. This oversight allows the original implementation to be executed, which can lead to unintended consequences. Specifically, the `balanceOfBatch` function returns the actual balance of the spe...

Vulnerable code:
```\nfunction balanceOf(address _wearer, uint256 _hatId)\n    public\n    view\n    override(ERC1155, IHats)\n    returns (uint256 balance)\n{\n    Hat storage hat = _hats[_hatId];\n\n    balance = 0;\n\n    if (_isActive(hat, _hatId) && _isEligible(_wearer, hat, _hatId)) {\n        balance = super.balanceOf(_wearer, _hatId);\n    }\n}\n```\n```\nfunction balanceOfBatch(address[] calldata owners, uint256[] calldata ids)\n    public\n    view\n    virtual\n    returns (uint256[] memory balances)\n{\n    require(owners.length == ids.length, "LENGTH_MISMATCH");\n\n    balances = new uint256[](owners.length);\n\n    unchecked {\n        for (uint256 i = 0; i < owners.length; i++) {\n            balances[i] = _balanceOf[owners[i]][ids[i]];\n        }\n    }\n}\n```