Radar by SecureChain AI

Wen Cat (WENCAT) security report

Radar by SecureChain AI scanned the verified Wen Cat source on BNB Smart Chain. Findings include an external processor with unlimited allowance, mandatory dividend callbacks that can revert transfers, and owner-controlled migration restrictions. Slither was not run.

The contract does not expose an owner mint function or blacklist function, but it relies on a configured external tax processor with unlimited token allowance, an external dividend contract that can veto transfers, and owner-controlled migration states that restrict pool transfers. These are material security and operational risks.

Trust score: 48/100. Source verified: Yes. Chain: bsc. Contract: 0xb596fc1980ba251b25b1d4bed33cb0b91bc17777.

This report was last modified on 2026-10-13 and contains 4 material findings.

high finding: External tax processor receives unlimited allowance and can control accrued tax tokens

The token grants the configured taxProcessor an unlimited ERC-20 allowance whenever tax liquidation occurs. The external processor can then pull tokens from the token contract, and if processing fails, the contract directly transfers its remaining token balance to that processor. A compromised, malicious, or incorrectly configured processor can therefore take control of tax tokens held by the token contract.

Evidence: In _processTax(), the contract calls _approve(address(this), taxProcessor, type(uint256).max) when the allowance is insufficient, then calls ITaxProcessor(taxProcessor).processTaxTokens(taxAmount). In the catch branch, it executes _plainTransfer(address(this), taxProcessor, remainingBalance), transferring the entire remaining token balance to the external processor.

Recommendation: Use a bounded allowance equal to the current tax amount, avoid automatically transferring all remaining tokens on failure, and add a governed recovery or processor-replacement mechanism. Validate the processor implementation and document its ability to pull token balances.

medium finding: Dividend contract failures can block ordinary token transfers

When dividendContract is nonzero, every transfer involving a non-exempt address calls the external dividend contract. Any revert from setShare causes the token transfer to revert, allowing a broken, unavailable, or hostile dividend contract to create a transfer lock for affected accounts.

Evidence: _afterTokenTransfer() calls IDividend(dividendContract).setShare(from, balanceOf(from)) and setShare(to, balanceOf(to)) for non-exempt addresses. Both calls catch failures and revert with DividendShareUpdateFailed. There is no owner function in this contract to replace or disable dividendContract after initialization.

Recommendation: Do not make balance transfers depend on a mandatory external callback. Use a non-blocking try/catch path, an explicit pause-resistant fallback, or a governed method to disable or replace a failed dividend contract.

medium finding: Owner controls pool states that can restrict or alter trading behavior

The owner can start and finalize migration, controlling when the token leaves BondingCurve and enters tax-enforced states. While in BondingCurve, any transfer to or from a configured pool reverts. Finalization also establishes the tax and anti-farmer expiration timestamps, so the owner controls the timing of these restrictions and tax phases.

Evidence: startMigration() and finalizeMigration() are both onlyOwner. In _transfer(), PoolState.BondingCurve requires !pools[from] && !pools[to], reverting transfers involving configured pools. finalizeMigration() changes the state to TaxEnforcedAntiFarmer and sets expiration times using block.timestamp.

Recommendation: Use explicit launch parameters and timelocks for state transitions, publish the configured pool and migration schedule, and consider removing discretionary owner control after launch or placing it behind a transparent governance process.

medium finding: Initializer accepts tax rates that can make pool transfers revert

The initializer accepts uint16 buy and sell tax rates without enforcing a maximum of 10000 basis points. A configured rate above 10000 makes tax exceed the transfer amount, causing the subtraction in _taxedTransfer() to underflow and revert whenever that tax path is used. The supplied initialization values are not available for verification.

Evidence: initialize() stores params.buyTax and params.sellTax directly in poolState. _getTaxWithPoolState() calculates amount * rate / 10000, while _taxedTransfer() executes uint256 remainingAmount = amount - tax. Rates above 10000 can therefore cause a checked-arithmetic revert.

Recommendation: Require buyTax and sellTax to be at most 10000 during initialization, or cap the calculated tax before subtraction. Verify the deployed initialization parameters and test all migration and tax states.