DEBTCATS (DEBTCATS) security report
SecureChain AI Radar independently reviewed the verified DEBTCATS source and supplied GoPlus evidence. Slither was not run. No direct mint, blacklist, proxy, or obvious honeypot mechanism was identified. Medium risks include unrestricted initializer tax rates that can block or confiscate sells, an external dividend callback that can revert ordinary transfers, and owner-controlled migration that can keep pool trading restricted. Current deployed tax rates and pool state require verification.
The contract is not shown to contain an unrestricted mint, blacklist, proxy upgrade, or obvious direct theft path. However, the initializer accepts unrestricted buy and sell tax rates, and transfers can revert whenever the configured dividend contract rejects a share update. Migration is owner-controlled and can keep pool transfers restricted while the token remains in BondingCurve state. Slither was skipped, and the current pool state and tax rates were not provided.
Trust score: 68/100. Source verified: Yes. Chain: bsc. Contract: 0x3247eb7f374c57ef267c12f4abc3f31c2a907777.
This report was last modified on 2026-09-19 and contains 3 material findings.
medium finding: Initializer permits confiscatory or sale-blocking tax rates
The initializer accepts uint16 buyTax and sellTax values without enforcing a maximum of 10000 basis points. A sell tax above 10000 causes `amount - tax` to revert in `_taxedTransfer`, blocking transfers to configured pools. A 10000 basis-point sell tax transfers the entire sell amount as tax, leaving the seller with zero tokens delivered to the pool.
Evidence: `initialize()` directly stores `params.buyTax` and `params.sellTax` in `poolState` without validation. `_getTaxWithPoolState()` computes `amount * currentPoolState.sellTaxRate / 10000`, while `_taxedTransfer()` executes `uint256 remainingAmount = amount - tax`. GoPlus supplied empty buy-tax and sell-tax values, so the deployed rates could not be confirmed from the evidence.
Recommendation: Validate both tax parameters during initialization with `require(rate <= 10000)`, preferably with a lower documented maximum. Verify the deployed buy and sell rates and test buy, sell, and wallet transfers in each pool state.
medium finding: External dividend contract can halt ordinary token transfers
Every transfer involving a non-excluded address invokes `IDividend(dividendContract).setShare()`. If either call reverts, the custom error is propagated and the entire token transfer reverts. A malfunctioning, incompatible, or intentionally rejecting dividend contract can therefore create a broad transfer denial of service.
Evidence: `_afterTokenTransfer()` calls `setShare(from, balanceOf(from))` and `setShare(to, balanceOf(to))` inside try/catch blocks, then executes `revert DividendShareUpdateFailed(...)` on failure. The dividend contract address is supplied during `initialize()` and there is no fallback, timeout, or owner-controlled replacement function.
Recommendation: Avoid making core ERC20 transfers depend on a mandatory external callback. Use non-blocking share accounting, queue failed updates, or provide a carefully governed recovery mechanism. Verify the configured dividend contract and test behavior when it rejects or runs out of gas.
medium finding: Owner-controlled migration can leave pool trading restricted
While the pool state is BondingCurve, all transfers to or from any configured pool revert. Only the owner can move the contract through `startMigration()` and `finalizeMigration()`. If the owner does not complete migration, or if ownership was renounced before completion, trading through the configured pools can remain unavailable indefinitely.
Evidence: `_transfer()` requires `!pools[from] && !pools[to]` in `PoolState.BondingCurve`. Both state-transition functions are protected by `onlyOwner`. GoPlus reports `owner_address` as the zero address, but the supplied evidence does not include the current `state`, so an active permanent restriction cannot be confirmed.
Recommendation: Confirm the live pool state and migration history. Use an immutable or time-bounded migration design, enforce valid state transitions, and ensure ownership cannot be renounced before migration is complete unless the token is already in a tradable state.