Radar by SecureChain AI

BSCZ (BSCZ) security report

Radar by SecureChain AI AI-scanned BSCZ’s verified source on BNB Smart Chain. Material findings include an uninitialized-proxy takeover path, unconstrained tax rates that may revert pool transfers, dividend callback transfer blocking, and owner-controlled launch transitions. Slither was not run.

The source contains material control and availability risks. The most serious conditional issue is an uninitialized-proxy takeover through initialize(), which can redirect the initial supply and ownership to an attacker. No unrestricted post-initialization mint function, blacklist function, or proxy upgrade function is present in the supplied contract source. Slither was skipped, so this report is based on source review plus the supplied GoPlus signals.

Trust score: 55/100. Source verified: Yes. Chain: bsc. Contract: 0x59d18aeed4e7e385bb53f8241b38eb51b7007777.

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

high finding: Uninitialized proxy can be claimed and configured by the first caller

initialize() is externally callable with the initializer modifier but has no deployment-time caller restriction. If a proxy is deployed without atomically invoking initialize(), the first caller can choose the token configuration, become the Ownable owner, and receive the entire initial mint. This can redirect the token’s supply and operational control.

Evidence: FlapTaxTokenV3.initialize(InitParams memory params) is external and calls __Ownable_init(), which assigns ownership to _msgSender(). The same function executes _mint(msg.sender, maxSupply), where maxSupply is 1e9 ether. The constructor only calls _disableInitializers() on the implementation, which does not initialize or lock a separate proxy’s storage.

Recommendation: Initialize every proxy atomically during deployment using trusted parameters, verify the Initialized and OwnershipTransferred events, and add deployment safeguards that prevent an uninitialized proxy from remaining callable. Confirm the deployed proxy’s initialization state independently.

medium finding: Initialization permits tax rates above 100%, potentially locking pool transfers

The initializer accepts uint16 buy and sell tax rates without enforcing a maximum of 10000 basis points. In a tax-enforced state, a rate above 10000 makes tax exceed the transfer amount, so amount - tax reverts. Pool buys or sells subject to that rate can therefore become unavailable.

Evidence: initialize() stores params.buyTax and params.sellTax directly in poolState without a <= 10000 check. _getTaxWithPoolState() calculates (amount * currentPoolState.buyTaxRate) / 10000 or the equivalent sell calculation, and _taxedTransfer() executes uint256 remainingAmount = amount - tax.

Recommendation: Validate both configured tax rates with require(rate <= 10000) during initialization. If rates above 100% are intentionally supported, define explicit behavior that does not underflow or revert ordinary pool transfers, and test all state transitions.

medium finding: External dividend callback can block token transfers

When dividendContract is configured, ordinary transfers call an external setShare callback after balances are changed. Any callback revert is propagated as DividendShareUpdateFailed, causing the entire token transfer to revert. A broken, incompatible, or unavailable dividend contract can therefore create a transfer-availability failure for non-excluded addresses.

Evidence: _afterTokenTransfer() calls IDividend(dividendContract).setShare(from, balanceOf(from)) and setShare(to, balanceOf(to)) inside try/catch blocks. Each catch executes revert DividendShareUpdateFailed(...). dividendContract is set during initialize() and there is no setter in the supplied contract to replace it after deployment.

Recommendation: Use a failure-tolerant dividend update design, such as recording pending share updates instead of reverting transfers, or provide a tightly governed recovery mechanism to disable or replace a failed dividend contract. Test behavior when the callback reverts or consumes excessive gas.

medium finding: Owner controls launch-state transitions and can delay pool functionality

The owner controls when the contract leaves BondingCurve and when tax enforcement begins. While in BondingCurve, all transfers to or from configured pools revert. This creates centralized launch and migration control and can delay pool interaction until the owner calls the required transition functions.

Evidence: startMigration() and finalizeMigration() are both onlyOwner. In _transfer(), PoolState.BondingCurve requires !pools[from] && !pools[to], reverting transfers involving configured pools. The contract has no permissionless transition or time-based fallback from BondingCurve.

Recommendation: Document the owner’s launch authority, use a multisignature or timelocked control process, and consider a permissionless or time-bounded migration path if indefinite launch-state control is not required.