Radar by SecureChain AI

Zipcoins (ZC) security report

Radar AI scanned the verified Zipcoins contract. GoPlus returned no signals; Slither was not run.

These controls can materially impair exits or enable liquidity removal if the owner exercises them.

Trust score: 28/100. Source verified: Yes. Chain: ethereum. Contract: 0xea337b15a3d4ebcac1c48b989cf8e1c133292458.

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

high finding: Owner can raise sell fees to 99%

The owner can change sell marketing, liquidity, and development fees at any time. The only enforced limit is sellTotalFees <= 99, allowing a sell to transfer as little as 1% of the requested amount to the seller while routing the remainder to the contract for fee processing.

Evidence: updateSellFees(...) is onlyOwner and computes sellTotalFees = sellMarketingFee + sellLiquidityFee + sellDevFee, then requires only sellTotalFees <= 99. In _transfer, sells calculate fees = amount.mul(sellTotalFees).div(100) and reduce the recipient amount by those fees.

Recommendation: Use immutable or tightly capped fees, or require governance/timelock approval for fee changes. Publish and monitor the current fee values and owner permissions.

high finding: Liquidity tokens are sent directly to the owner

When trading is enabled, the contract adds its token and ETH balances to the Uniswap V2 pair with the LP recipient set to owner(). The owner therefore receives the LP tokens and can potentially remove the liquidity represented by those tokens, creating a material liquidity-withdrawal risk.

Evidence: enableTrading() calls uniswapV2Router.addLiquidityETH{ value: address(this).balance }(address(this), totalSupply(), 0, 0, owner(), block.timestamp). No lock, timelock, burn, or permanently controlled LP recipient is implemented.

Recommendation: Send LP tokens to a verifiable locker, burn address, or governed custody mechanism, and document the lock duration and withdrawal rules.

medium finding: Owner can impose blacklist state, although the supplied source does not enforce it

The owner can set _blacklist entries, but _transfer never checks _blacklist. This is a control-design risk because the exposed blacklist interface may create misleading expectations about transfer restrictions, while any future implementation change could activate owner-controlled blocking without an accompanying governance constraint.

Evidence: blacklistAccount(address,bool) is public onlyOwner and writes _blacklist[account]. The shown _transfer implementation contains no require or branch reading _blacklist.

Recommendation: Remove the unused blacklist interface or explicitly document that it has no effect; if blacklist functionality is intended, constrain it with transparent criteria and governance.

medium finding: Owner controls whether trading is enabled

Trading starts disabled, and ordinary transfers are rejected while limitsInEffect is true unless the sender or recipient is fee-excluded. The owner alone can call enableTrading(), which also enables swapping and removes limits. This creates centralized launch and transfer-control risk before activation.

Evidence: tradingActive is initialized to false. In _transfer, when !tradingActive, transfers require _isExcludedFromFees[from] || _isExcludedFromFees[to]. enableTrading() is external onlyOwner and sets tradingActive = true, swapEnabled = true, and limitsInEffect = false.

Recommendation: Use a transparent launch procedure, publish the activation conditions, and consider removing discretionary owner control through a timelock or renounced/governed administration after deployment.

medium finding: Fee proceeds are routed through owner-changeable wallets

The owner can replace both fee recipient addresses without delay. Swap processing sends development ETH to devWallet and then sends the contract's remaining ETH balance to marketingWallet, so fee destinations are fully dependent on owner-controlled addresses.

Evidence: updateDevWallet(...) and updateMarketingWallet(...) are onlyOwner. swapBack() performs low-level calls to devWallet and marketingWallet, with the latter receiving address(this).balance and its call required to succeed.

Recommendation: Use immutable or governed fee recipients, add recipient validation and transparent limits, and document the fee distribution policy.