Radar by SecureChain AI

Tokenize Everything (万物上链) security report

SecureChain AI scanned the verified Tokenize Everything contract on BSC. GoPlus reports no honeypot, minting, blacklist, pause, proxy, or selfdestruct indicators. Source review found medium risks involving dividend callback transfer blocking, external tax-processor custody, expiry transitions that occur only on main-pool sells, and initializer tax rates that are not capped at 100%. Slither was not run.

The contract does not show an obvious unrestricted mint, blacklist, proxy upgrade, or direct honeypot path. GoPlus reports is_honeypot=0, is_mintable=0, transfer_pausable=0, and owner_address=0x0. However, transfers can be blocked by the configured dividend contract, collected taxes are delegated to an external tax processor, and deployment parameters can create excessive-tax or delayed-expiry risks.

Trust score: 63/100. Source verified: Yes. Chain: bsc. Contract: 0x2740fac3c69aab40c18ec90fee62500fa5be7777.

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

medium finding: External dividend callback can block ordinary token transfers

Every transfer involving a non-excluded sender or recipient calls dividendContract.setShare(). If either callback reverts, the token transfer reverts through DividendShareUpdateFailed. A malfunctioning, restrictive, or compromised dividend contract can therefore prevent users from transferring tokens, except for excluded pool, token-contract, zero, dead, and dividend addresses.

Evidence: In _afterTokenTransfer(), IDividend(dividendContract).setShare(from, balanceOf(from)) and setShare(to, balanceOf(to)) are wrapped in try/catch that explicitly reverts on failure. dividendContract is assigned during initialize() and there is no setter in the verified source. The supplied GoPlus evidence does not validate the dividend contract's behavior.

Recommendation: Use a non-blocking dividend update pattern, queue failed updates, or provide a permissionless recovery mechanism. Independently audit and monitor the configured dividend contract and verify that it cannot reject valid setShare calls.

medium finding: Collected tax tokens are entrusted to an external tax processor

The token grants the configured taxProcessor an effectively unlimited allowance and sends all accrued tax tokens to it for processing. If that external contract is incorrectly configured, compromised, or economically unsafe, collected tax tokens can be misdirected or become unrecoverable. This does not directly authorize the processor to spend user balances, but it creates material custody and dependency risk over protocol fees.

Evidence: _processTax() approves taxProcessor for type(uint256).max when needed and calls processTaxTokens(taxAmount). On failure, it transfers the remaining token balance held by this contract directly to taxProcessor. taxProcessor is set during initialize() and has no update function. GoPlus reports external_call=0 for its detector, but that signal does not establish the safety of the configured external processor.

Recommendation: Validate the processor address and implementation at deployment, avoid unconditional fallback transfers to the processor, use bounded allowances, add transparent accounting and recovery controls, and independently audit the processor and its downstream receivers.

medium finding: Tax expiry is processed only on sells to the main pool

Tax and anti-farmer expiry timestamps are checked only inside _liquidateTax(), which is invoked before transfers and performs state transitions only when to == mainPool. If no sell to mainPool occurs after an expiry timestamp, taxes can remain active on buys, transfers involving other configured pools, and other operations beyond their intended duration. The first qualifying sell may transition state and avoid tax on that transaction, creating timing-dependent behavior.

Evidence: _liquidateTax() enters its state-transition logic only when to == mainPool. The checks for block.timestamp > taxExpirationTime and block.timestamp > antiFarmerExpirationTime are nested inside that condition. _getTaxWithPoolState() can apply taxes to all pools during TaxEnforcedAntiFarmer.

Recommendation: Evaluate expiry on every transfer or expose a permissionless state-finalization function. Add tests covering expiry with no main-pool sells and document the exact tax transition semantics.

medium finding: Initialization permits tax rates above 100%, which can lock pool interactions

The initializer accepts uint16 buy and sell tax rates without enforcing a maximum of 10,000 basis points. A rate above 100% makes tax greater than or equal to the transfer amount; _taxedTransfer() then calculates amount - tax and reverts on underflow. This can disable buys or sells for the affected pool direction. The supplied evidence does not include the live buy and sell tax values, so the current deployment impact is unconfirmed.

Evidence: initialize() stores params.buyTax and params.sellTax directly in poolState. _getTaxWithPoolState() calculates amount * rate / 10000, while _taxedTransfer() executes uint256 remainingAmount = amount - tax. No require limits either rate to <=10000.

Recommendation: Enforce buyTax <= 10000 and sellTax <= 10000 during initialization, preferably with a lower protocol policy cap. Verify the deployed poolState and publish the active rates.

medium finding: Owner-controlled migration can delay or prevent the intended trading state

Only the owner can call startMigration() and finalizeMigration(). Before migration, transfers to or from any configured pool revert in BondingCurve state. If ownership is renounced or the owner becomes unavailable before finalization, the contract can remain in a state where pool interaction is restricted. GoPlus reports the current owner address as zero, making the deployment's migration state and operational assumptions important to verify.

Evidence: _transfer() requires !pools[from] && !pools[to] in BondingCurve state. startMigration() and finalizeMigration() are both onlyOwner. GoPlus reports owner_address=0x0000000000000000000000000000000000000000 and owner_balance=0.

Recommendation: Use an explicit, verifiable launch state machine with permissionless or time-bounded finalization where appropriate. Confirm the current state(), poolState(), and historical ownership events before relying on the token's trading configuration.