Radar by SecureChain AI

STOCKCOM (STOCKCOM) security report

Radar by SecureChain AI scanned STOCKCOM's verified source. Findings include unrestricted initialization-time tax rates, owner-controlled migration, and transfer dependence on an external dividend contract.

STOCKCOM is not free of material contract risks. The verified source does not show post-initialization tax setters or public minting, consistent with GoPlus reporting is_mintable=0. However, initialization parameters control tax rates and external callback addresses, while transfer execution can revert when the configured dividend contract rejects share updates.

Trust score: 42/100. Source verified: Yes. Chain: bsc. Contract: 0x4e9cac0605e1e6965c54fa5f5446b93620d97777.

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

high finding: Initialization can grant ownership and the entire initial supply to the caller

The external initialize function is protected only by the one-time initializer guard. It sets the caller as owner through __Ownable_init() and mints maxSupply, defined as 1e9 ether, directly to msg.sender. If a deployed proxy or clone is left uninitialized, the first caller can become owner and receive the full initial supply.

Evidence: FlapTaxTokenV3.initialize(...) is external and uses the initializer modifier, then calls __Ownable_init() and _mint(msg.sender, maxSupply). The constructor disables initialization only on the implementation contract; proxy initialization state must be verified separately. GoPlus reports is_proxy=0, but the supplied ABI and source do not establish that the deployed address is already initialized.

Recommendation: Verify the deployed contract's Initialized event, owner, totalSupply, and initialization storage state. Initialize atomically at deployment, restrict factory-created clones to trusted launch parameters, and ensure implementation and deployment addresses cannot be initialized unexpectedly.

medium finding: Initializer can configure confiscatory buy and sell taxes

The initializer accepts buyTax and sellTax as unrestricted uint16 values and stores them as basis-point rates. A value up to 65535 is accepted, allowing tax calculations that can consume almost the entire transfer amount when pool taxation is active. There is no source-level cap such as a 10000-basis-point maximum and no post-deployment user-controlled adjustment or disclosed validation in this contract.

Evidence: initialize(...) assigns buyTax: params.buyTax and sellTax: params.sellTax. _getTaxWithPoolState computes (amount * currentPoolState.buyTaxRate) / 10000 or the corresponding sell rate. Pool transfers use these values in TaxEnforcedAntiFarmer and TaxEnforced states.

Recommendation: Enforce an explicit maximum rate of 10000 basis points or a lower documented limit during initialization, publish the configured rates, and test buy and sell behavior across every pool state before enabling trading.

medium finding: Dividend callback can block ordinary token transfers

When dividendContract is nonzero, every transfer involving a non-exempt address invokes IDividend.setShare for the sender and recipient. Any revert from either callback is caught and converted into DividendShareUpdateFailed, reverting the entire token transfer. A faulty, incompatible, or unavailable dividend contract can therefore create a material transfer denial of service.

Evidence: _afterTokenTransfer(...) calls IDividend(dividendContract).setShare(from, balanceOf(from)) and setShare(to, balanceOf(to)) unless the address is the token contract, zero address, dead address, dividend contract, or a configured pool. The catch blocks execute revert DividendShareUpdateFailed(...). dividendContract is supplied during initialize and has no setter in the shown contract.

Recommendation: Avoid making core ERC20 transfers depend on an external callback, or use failure-tolerant accounting with bounded gas and a recovery path. Validate the dividend contract during initialization and provide a documented migration or disable mechanism if the dependency fails.

medium finding: Owner-controlled migration state can restrict pool transfers

The owner alone controls startMigration and finalizeMigration. While the token remains in BondingCurve, any transfer to or from an address marked in pools reverts. The source provides no timelock, permission separation, or public fallback that forces migration to complete, so the owner can control when configured pool trading becomes possible.

Evidence: startMigration() and finalizeMigration() are onlyOwner. In _transfer, BondingCurve state executes require(!pools[from] && !pools[to], "Transfers to/from pools are restricted in BondingCurve state"). The pool state is initialized to BondingCurve.

Recommendation: Use a permissionless or time-bounded launch transition where appropriate, document the owner-controlled lifecycle, and add monitoring or governance controls around migration state changes.

medium finding: Tax liquidation delegates token handling to an external processor with an unlimited allowance

During liquidation, the token contract grants taxProcessor type(uint256).max allowance and calls processTaxTokens. If processing fails, the catch path transfers the token contract's entire remaining token balance to taxProcessor, not merely the current taxAmount. This creates a strong trust dependency on the configured external processor and can expose accumulated tax tokens to that address.

Evidence: _processTax(...) sets _approve(address(this), taxProcessor, type(uint256).max) when needed. On failure it executes _plainTransfer(address(this), taxProcessor, remainingBalance), where remainingBalance is balanceOf(address(this)). taxProcessor is set during initialization and is not changeable in the shown contract.

Recommendation: Limit approvals to the amount being processed, avoid transferring all residual balances in an error path, validate processor code and configuration, and add governance or emergency controls for processor replacement.