MOTX (MOTX) security report
Radar by SecureChain AI reviewed the verified MOTX contract on BNB Smart Chain. Material findings include owner-controlled pool restrictions, external tax-processor dependency, dividend callback transfer blocking, and missing tax-rate bounds.
MOTX does not expose an owner mint, blacklist, or post-deployment tax setter in the verified source. However, the owner can keep the configured pool in BondingCurve state, where transfers to and from pools are rejected. In addition, a configured tax processor can receive all accumulated tax tokens when processing fails, and a configured dividend contract can block ordinary transfers by reverting share updates.
Trust score: 57/100. Source verified: Yes. Chain: bsc. Contract: 0x5828b50cd6cea702638d91e892fe6ccf73007777.
This report was last modified on 2026-10-08 and contains 4 material findings.
medium finding: Owner can indefinitely restrict configured pool trading before migration
The owner exclusively controls startMigration() and finalizeMigration(). While the pool state remains BondingCurve, every transfer involving any configured pool reverts, allowing the owner to delay or prevent pool buys and sells until migration is started.
Evidence: In _transfer(), the BondingCurve branch requires !pools[from] && !pools[to], otherwise it reverts with "Transfers to/from pools are restricted in BondingCurve state". Both state transitions are protected by onlyOwner, and initialize() marks the supplied pool addresses in pools.
Recommendation: Use an immutable or independently governed migration process, publish explicit migration conditions, and provide a verifiable emergency path that cannot be controlled by one owner account.
medium finding: Tax-processing failure forwards the entire accumulated tax balance to the tax processor
If the external tax processor call fails, the contract transfers its remaining MOTX balance to taxProcessor instead of retaining the balance or retrying safely. A faulty or intentionally reverting processor can therefore capture accumulated tax tokens.
Evidence: _processTax() calls ITaxProcessor(taxProcessor).processTaxTokens(taxAmount) inside try/catch. In the catch branch it reads balanceOf(address(this)) and calls _plainTransfer(address(this), taxProcessor, remainingBalance). taxProcessor is supplied during initialize() and has no replacement function in this contract.
Recommendation: Do not transfer the full balance on failure. Preserve accrued tax, emit a recoverable failure state, add bounded retry or governance-controlled recovery, and validate the processor implementation before initialization.
medium finding: Dividend callback can block all non-exempt transfers
When dividendContract is configured, ordinary transfers synchronously call setShare() for the sender and recipient. Any revert from that external contract causes the token transfer to revert, creating a transfer-denial dependency on the dividend implementation.
Evidence: _afterTokenTransfer() calls IDividend(dividendContract).setShare(from, balanceOf(from)) and setShare(to, balanceOf(to)) for non-exempt addresses. Each call is wrapped in try/catch, but the catch explicitly reverts with DividendShareUpdateFailed.
Recommendation: Avoid making balance transfers depend on a synchronous external callback. Consider non-blocking share accounting, bounded failure handling, or a trusted and upgrade-controlled dividend module with tested availability guarantees.
medium finding: Initialization parameters can configure transfer-breaking tax rates
The initializer accepts buy and sell tax rates as uint16 values without checking that they are at most 10000 basis points. If a rate above 10000 is supplied, taxed pool transfers can underflow when calculating the remaining amount and revert.
Evidence: initialize() stores params.buyTax and params.sellTax directly in poolState. _getTaxWithPoolState() computes amount * rate / 10000, while _taxedTransfer() calculates uint256 remainingAmount = amount - tax. Rates up to 65535 are representable by uint16.
Recommendation: Require both tax rates to be no greater than 10000 during initialization, and verify deployment parameters before enabling migration or pool trading.