WePay (WEPAY) security report
SecureChain AI scanned the verified WePay contract and reviewed GoPlus evidence. No Slither scan was run. Material findings include approximately 96.10% owner concentration, owner-controlled migration that can restrict pool transfers, initialization-dependent tax risks, and external dividend and tax-processor dependencies.
The contract is not shown to have an immediately exploitable mint or blacklist backdoor, but it carries meaningful owner-concentration and migration-control risks. Trading through configured pools can remain restricted until the owner starts migration, and initialization parameters can create severe tax or transfer behavior. Independent review is required before treating the token as low risk.
Trust score: 48/100. Source verified: Yes. Chain: bsc. Contract: 0x39fd09cf743dcb4838ea34f35495f6b216767777.
This report was last modified on 2026-09-29 and contains 4 material findings.
high finding: Owner controls whether pool transfers remain restricted or become active
The owner alone can call startMigration and finalizeMigration. While the pool state is BondingCurve, _transfer reverts whenever either endpoint is a configured pool. The owner can therefore keep transfers to and from the configured trading pools disabled indefinitely by not starting migration. Conversely, startMigration immediately moves the token into a state where pool transfers are unrestricted until finalization.
Evidence: FlapTaxTokenV3._transfer requires !pools[from] && !pools[to] in PoolState.BondingCurve. startMigration is onlyOwner and changes BondingCurve to Migrating; finalizeMigration is also onlyOwner and changes Migrating to TaxEnforcedAntiFarmer.
Recommendation: Document the migration authority and expected timeline. Use a timelock or governance-controlled transition, publish the configured pool addresses and state, and verify state transitions before users trade.
medium finding: Initialization permits tax rates that can block pool transfers
The initializer accepts buyTax and sellTax as uint16 values but does not enforce a maximum of 10000 basis points. If a configured tax rate is greater than 10000, _taxedTransfer computes remainingAmount = amount - tax and reverts when the tax exceeds the transfer amount. This can make buys or sells involving configured pools fail during tax-enforced states.
Evidence: initialize stores params.buyTax and params.sellTax directly in poolState without bounds checks. _getTaxWithPoolState calculates amount * rate / 10000, while _taxedTransfer subtracts the result from amount. The supplied ABI does not disclose the deployed buy and sell values, so current exploitation is not proven.
Recommendation: Enforce buyTax <= 10000 and sellTax <= 10000, preferably with a lower documented maximum. Verify the deployed poolState tax values and test buy and sell paths under the live configuration.
medium finding: External dividend callback can freeze ordinary transfers
For transfers where the sender or recipient is not excluded, _afterTokenTransfer calls dividendContract.setShare. Any revert from that external contract is propagated as DividendShareUpdateFailed, reverting the entire token transfer. A broken, paused, incompatible, or malicious dividend contract can therefore block ordinary wallet transfers and can also affect user interactions around trading pools when the user side is not excluded.
Evidence: _afterTokenTransfer calls IDividend(dividendContract).setShare for non-excluded from and to addresses inside try/catch, then explicitly reverts on catch. dividendContract is set during initialize and there is no setter or recovery function in FlapTaxTokenV3.
Recommendation: Validate the dividend contract before initialization, require a non-blocking callback design, or isolate share-accounting failures from token transfers. Verify the configured dividend contract behavior and authorization for setShare.
medium finding: Tax liquidation depends on a trusted external processor and can redirect all accrued tax tokens
During liquidation, the token grants taxProcessor an effectively unlimited allowance and calls processTaxTokens. If that call reverts, the catch branch transfers the entire token balance held by the token contract directly to taxProcessor. This creates a strong dependency on the configured processor and permits processor-side behavior to determine the custody and handling of accumulated tax tokens.
Evidence: _processTax sets allowance(address(this), taxProcessor) to type(uint256).max when needed. On processTaxTokens failure, it executes _plainTransfer(address(this), taxProcessor, remainingBalance), where remainingBalance is the full token-contract balance. taxProcessor is assigned during initialize and cannot be changed by this contract.
Recommendation: Use a narrowly scoped allowance, separate failed-liquidation recovery from automatic transfer, and require audited processor code with immutable or governance-controlled configuration. Monitor processor approvals and tax-balance movements.