Radar by SecureChain AI

破茧成蝶 (破茧成蝶) security report

Radar AI scanned the verified 破茧成蝶 contract on BNB Smart Chain. No critical or high issue was established, but medium risks affect dividend callbacks, tax processing, migration controls, and rate validation.

No critical or high-severity issue was established from the supplied source and evidence. Medium risks remain: a configured dividend contract can block transfers, the tax processor receives broad custody over accrued tax tokens, and pool transfers are restricted until owner-controlled migration changes the state.

Trust score: 62/100. Source verified: Yes. Chain: bsc. Contract: 0x0e262acafbce3e6e19be04d9c0cd5cbb85fb7777.

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

medium finding: Dividend contract failure can block ordinary token transfers

When dividendContract is nonzero, every transfer involving a nonexcluded address calls IDividend.setShare. Any revert from that external call is propagated through DividendShareUpdateFailed, causing the token transfer itself to revert. A broken, malicious, or unavailable dividend contract can therefore create a transfer denial of service for affected addresses.

Evidence: In _afterTokenTransfer, shouldSkipFrom and shouldSkipTo only exclude the token contract, zero address, dead address, dividendContract, and configured pools. For other addresses, IDividend(dividendContract).setShare(...) is called inside try/catch, and the catch block executes revert DividendShareUpdateFailed(...). The dividendContract address is supplied during initialize and is not changeable afterward.

Recommendation: Use a nonblocking dividend-share update path, isolate dividend accounting from ERC-20 transfers, or explicitly validate and governance-control the dividend contract. Add emergency handling that can disable dividend callbacks without preventing token transfers.

medium finding: Tax processor has broad custody over accumulated tax tokens

The configured taxProcessor is granted an effectively unlimited allowance over tokens held by the token contract. It is also the recipient of the entire remaining token balance if tax processing reverts. Compromise, misconfiguration, or malicious behavior in that external processor could divert accrued tax tokens and disrupt the intended tax distribution.

Evidence: In _processTax, the token contract approves taxProcessor for type(uint256).max whenever the current allowance is below taxAmount, then calls ITaxProcessor(taxProcessor).processTaxTokens(taxAmount). If that call fails, the catch block reads balanceOf(address(this)) and transfers the entire remainingBalance directly to taxProcessor. taxProcessor is assigned from initialize(params) and has no setter or replacement function in FlapTaxTokenV3.

Recommendation: Restrict allowance to the exact amount, avoid transferring unrelated residual balances on failure, use a controlled recovery process, and apply governance or timelock controls to the external processor implementation and configuration.

medium finding: Pool transfers are centrally gated during the bonding-curve state

While poolState.state is BondingCurve, every transfer involving any configured pool reverts. The contract depends on owner-controlled startMigration and finalizeMigration calls to leave this state and enable pool transfers. If migration is delayed, misconfigured, or not completed, trading through configured pools remains unavailable.

Evidence: In _transfer, the BondingCurve branch requires !pools[from] && !pools[to], reverting with "Transfers to/from pools are restricted in BondingCurve state" otherwise. startMigration and finalizeMigration are both external onlyOwner functions, and initialize sets the initial state to PoolState.BondingCurve.

Recommendation: Use an explicit, verifiable migration state machine with bounded transition windows, validate pool configuration before initialization, and provide a transparent recovery process for an incomplete migration without relying on an indefinite privileged action.

medium finding: Initialization accepts tax rates above 100%, which can make pool trades revert

The initializer accepts uint16 buy and sell tax rates without enforcing a maximum of 10000 basis points. If either supplied rate exceeds 10000, the computed tax can exceed the transfer amount and amount - tax reverts, preventing the affected taxed pool trade path.

Evidence: initialize stores params.buyTax and params.sellTax directly in uint16 poolState fields. _getTaxWithPoolState computes (amount * currentBuyTaxRate) / 10000 or (amount * currentSellTaxRate) / 10000, while _taxedTransfer executes uint256 remainingAmount = amount - tax without a cap or validation.

Recommendation: Require buyTax and sellTax to be at most 10000 during initialization, and add tests covering boundary and over-100% configurations. Confirm deployed initialization parameters before relying on transferability.

medium finding: External tax processing is coupled to the sell transfer execution path

A sell to mainPool can trigger external tax processing before the transfer completes. Although the call is wrapped in try/catch, the downstream token and dividend callbacks can still revert the original transfer, creating operational fragility and making sell execution dependent on external contracts and gas behavior.

Evidence: _transfer calls _liquidateTax(to) before loading state and executing the user transfer. When to == mainPool and the state is tax-enforced, _liquidateTax may call _processTax, which invokes ITaxProcessor.processTaxTokens. Subsequent token movements can invoke _afterTokenTransfer and IDividend.setShare, whose failure reverts the transaction.

Recommendation: Move liquidation to an explicitly callable, bounded maintenance function or make all auxiliary accounting callbacks nonblocking. Add gas-limit, failure-isolation, and recovery tests for processor and dividend dependencies.