Radar by SecureChain AI

CStock (CStock) security report

Radar by SecureChain AI AI-scanned the verified CStock contract on BNB Smart Chain. Material findings include a dividend callback that can revert transfers, owner-controlled migration timing, permissive tax parameters, and external tax-processor custody risk. Slither was not run.

CStock does not expose post-initialization minting, pausing, blacklist, or owner-controlled tax setter functions in the reviewed source. However, the configured dividend contract can block normal transfers by reverting, the owner controls when migration leaves the pool-restricted state, and initialization accepts tax rates high enough to make trading fail or deliver no tokens. Slither was skipped.

Trust score: 38/100. Source verified: Yes. Chain: bsc. Contract: 0xe31bb621118cfe3ba2db6fcf68da9aa2b7767777.

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

high finding: Dividend callback can freeze ordinary token transfers

When dividendContract is nonzero, every transfer involving a non-excluded account calls dividendContract.setShare. Any revert is propagated as DividendShareUpdateFailed, causing the token transfer itself to revert. A broken, malicious, or incompatible dividend contract can therefore block buys, sells, and wallet-to-wallet transfers for affected accounts.

Evidence: In _afterTokenTransfer, setShare(from, balanceOf(from)) and setShare(to, balanceOf(to)) are called unless the address is the token contract, zero address, dead address, dividendContract, or a configured pool. Each call is wrapped in try/catch that reverts with DividendShareUpdateFailed on failure. The dividendContract address is supplied during initialize and there is no recovery or bypass function in FlapTaxTokenV3.

Recommendation: Validate the dividend implementation before initialization, monitor its setShare behavior, and add a trusted emergency bypass or fail-open design for share updates. Consider allowing the dividend contract to be disabled or replaced only through a governed, timelocked process.

medium finding: Owner controls migration timing and can keep configured pools restricted

The owner alone starts and finalizes migration. While the token remains in BondingCurve state, all transfers to or from configured pools revert. The owner can therefore delay the transition required for pool trading, creating a centralized availability dependency.

Evidence: startMigration() and finalizeMigration() are both onlyOwner. In _transfer, the BondingCurve branch requires !pools[from] && !pools[to], reverting with "Transfers to/from pools are restricted in BondingCurve state". No permissionless timeout or alternative transition path exists.

Recommendation: Use a transparent and time-bounded migration process, preferably controlled by a multisignature or timelock. Publish the intended migration conditions and provide an independently verifiable deadline or fallback transition.

medium finding: Initialization permits tax rates that can disable or severely impair pool trading

The initializer accepts buyTax and sellTax as uint16 values without a basis-point upper-bound check. Values above 10000 can make _taxedTransfer underflow and revert, while a 10000 basis-point rate directs the full transfer amount to the token contract and leaves the pool or recipient with zero tokens. The actual configured rates were not supplied, so this is a configuration-dependent risk rather than a confirmed live setting.

Evidence: initialize stores params.buyTax and params.sellTax directly in poolState. _getTaxWithPoolState calculates amount * rate / 10000, and _taxedTransfer computes remainingAmount = amount - tax. A uint16 permits values up to 65535, with no require limiting either rate to 10000 or less.

Recommendation: Enforce buyTax and sellTax <= 10000 during initialization, preferably with a lower protocol-specific maximum. Verify deployed initialization parameters and reject deployments whose rates exceed the documented limit.

medium finding: Tax liquidation depends on a fixed external processor and forwards all accrued tax on failure

The tax processor is configured at initialization and cannot be changed through the reviewed token contract. If processing reverts, the catch branch transfers the entire token balance held by the token contract to taxProcessor. This creates a material custody and configuration dependency: a compromised or incorrect processor can receive all accumulated tax tokens during a failed liquidation path.

Evidence: _processTax calls ITaxProcessor(taxProcessor).processTaxTokens(taxAmount). On catch, it reads balanceOf(address(this)) and calls _plainTransfer(address(this), taxProcessor, remainingBalance). taxProcessor is assigned in initialize and there is no setter or recovery function in FlapTaxTokenV3.

Recommendation: Use immutable or governed processor configuration, verify the processor implementation before deployment, restrict fallback transfers to the intended tax amount, and emit detailed recovery events. Add an emergency governance mechanism for processor replacement if the surrounding architecture permits it.