SI MUSE PAD (SIMP) security report
Radar AI scanned the verified SI MUSE PAD contract and reviewed GoPlus evidence. No Critical vulnerability was confirmed.
The verified source was independently AI-scanned and reviewed together with the supplied GoPlus evidence. No Critical issue was confirmed, but the contract has meaningful centralization and configuration risks.
Trust score: 55/100. Source verified: Yes. Chain: bsc. Contract: 0xf69c7bf48474e3fcdc5201d133ec4c5143307777.
This report was last modified on 2026-09-30 and contains 4 material findings.
medium finding: Owner can indefinitely control migration and restrict configured pool transfers
While the token remains in BondingCurve state, every transfer involving a configured pool reverts. Only the owner can call startMigration(), and only the owner can later call finalizeMigration(). The source provides no permissionless transition or deadline, so the owner can delay migration and keep configured pool trading transfers restricted.
Evidence: FlapTaxTokenV3._transfer() requires !pools[from] && !pools[to] in PoolState.BondingCurve. startMigration() and finalizeMigration() are both protected by onlyOwner. GoPlus identifies the contract owner as 0xe2ce6ab80874fa9fa2aae65d277dd6b8e65c9de0.
Recommendation: Use a permissionless or time-bounded migration process, publish the intended migration schedule, and place owner control behind a multisig or governance mechanism.
medium finding: Initialization permits tax rates that can make buys or sells revert
The initializer accepts uint16 buyTax and sellTax values without requiring either rate to be at most 10000 basis points. The tax calculation can therefore produce tax greater than amount, causing amount - tax in _taxedTransfer() to underflow and revert. If such parameters were used, transfers involving configured pools could become honeypot-like or otherwise untradeable during tax-enforced states.
Evidence: initialize() stores params.buyTax and params.sellTax without an upper-bound check. _getTaxWithPoolState() computes amount * rate / 10000, while _taxedTransfer() executes uint256 remainingAmount = amount - tax. The supplied GoPlus tax fields are blank, so the deployed effective rates were not established by the supplied evidence.
Recommendation: Require buyTax and sellTax <= 10000 during initialization, preferably enforce a lower protocol maximum, and expose or document validated launch parameters before trading begins.
medium finding: External dividend callback can lock ordinary token transfers
After transfers, the token synchronously calls dividendContract.setShare() for non-exempt sender and recipient addresses. Any revert from that external contract is converted into DividendShareUpdateFailed and reverts the entire token transfer. Because dividendContract is set during initialization and has no setter or fallback path in this contract, a misconfigured, unavailable, or incompatible dividend contract can prevent users from transferring tokens.
Evidence: _afterTokenTransfer() calls IDividend(dividendContract).setShare() and explicitly reverts in both catch blocks. The dividendContract address is assigned in initialize() and is not subsequently changeable in the supplied source. GoPlus reports external_call as 0, but that signal does not negate the source-level callback behavior.
Recommendation: Avoid making accounting callbacks mandatory for transfers; use non-blocking updates, a trusted and audited dividend implementation, or an explicit recovery mechanism that can disable dividend hooks without locking balances.
medium finding: Tax processing depends on a trusted external processor and can redirect accumulated tax tokens
When tax liquidation occurs, the token grants taxProcessor an effectively unlimited allowance and calls processTaxTokens(). If that call reverts, the catch branch transfers the entire remaining token balance held by the token contract directly to taxProcessor. This creates a strong trust and integration dependency: a malicious or malfunctioning processor can receive accumulated tax tokens or disrupt expected tax handling.
Evidence: _processTax() approves type(uint256).max to taxProcessor when needed. On a failed processTaxTokens() call, it executes _plainTransfer(address(this), taxProcessor, remainingBalance). taxProcessor is assigned during initialize() and is not changeable in the supplied contract.
Recommendation: Validate and govern the processor address, avoid unlimited approvals where practical, limit fallback transfers to a defined recovery policy, and add transparent accounting and emergency controls for failed liquidation.