Quantum Audit Logo

Is b-money Safe?

On-chain security analysis — is it a scam or legit?

Is this your token? Publish your own audit on this page →

b-money B-MONEY
0xf497…7777
BNB Chain Not verifiedLast checked 2d ago 1 audit on record
Executive SummaryAI Copilot

The FlapTaxTokenV3 contract implements an upgradeable ERC20 token with dynamic tax mechanisms and pool state management. The contract leverages OpenZeppelin's upgradeable standards, contributing to a robust architectural foundation. However, a critical reentrancy vulnerability exists in the tax liquidation process, potentially allowing users to bypass taxes during transfers. Additionally, significant centralization risk is present due to owner-controlled state transitions, and a denial-of-service vector could block all token transfers if the external tax processor reverts.

1 Critical2 Medium2 Low1 Informational
Volume 24h
$1.15M
Liquidity
$216.2K
Price
$0.00339
Token Age
8d
Top 10 Holders
24.9%

Security Findings

Critical

Reentrancy Vulnerability Leading to Tax Bypass

C-01The `_liquidateTax` function, called by `_transfer`, sets `poolState.notLiquidating` to `false` *before* making an external call to `ITaxProcessor.processTax`. If the `taxProcessor` contract is malicious or compromised, it can re-enter the `_transfer` function. During this re-entrant call, the `_liquidateTax` function will be called again. However, because `poolState.notLiquidating` is still `false` from the initial call, the tax processing logic within `_liquidateTax` will be skipped. More critically, the `_getTaxWithPoolState` function, which determines the tax amount for transfers, also checks `currentPoolState.notLiquidating`. If a re-entrant transfer occurs while `notLiquidating` is `f…
IssueThe `_liquidateTax` function, called by `_transfer`, sets `poolState.notLiquidating` to `false` *before* making an external call to `ITaxProcessor.processTax`. If the `taxProcessor` contract is malicious or compromised, it can re-enter the `_transfer` function. During this re-entrant call, the `_liquidateTax` function will be called again. However, because `poolState.notLiquidating` is still `false` from the initial call, the tax processing logic within `_liquidateTax` will be skipped. More critically, the `_getTaxWithPoolState` function, which determines the tax amount for transfers, also checks `currentPoolState.notLiquidating`. If a re-entrant transfer occurs while `notLiquidating` is `f…
FixImplement the Checks-Effects-Interactions pattern strictly. Ensure all state changes related to `notLiquidating` are finalized *before* any external calls. A reentrancy guard on `_liquidateTax` or `_transfer` would also mitigate this. For example, set `notLiquidating` back to `true` immediately after the `_processTax` call, or use OpenZeppelin's `ReentrancyGuard`.
StatusUnresolved
Medium

Centralization Risk with Owner-Controlled State Transitions

M-01Functions `startMigration` and `finalizeMigration` are protected by the `onlyOwner` modifier. These functions control critical state transitions of the token's economic model, including enabling and disabling tax enforcement and anti-farmer mechanisms. This grants a single address (the owner) significant power over the token's operational state, representing a single point of failure and a high degree of trust in the owner's benevolence and security practices.
IssueFunctions `startMigration` and `finalizeMigration` are protected by the `onlyOwner` modifier. These functions control critical state transitions of the token's economic model, including enabling and disabling tax enforcement and anti-farmer mechanisms. This grants a single address (the owner) significant power over the token's operational state, representing a single point of failure and a high degree of trust in the owner's benevolence and security practices.
FixConsider implementing a multi-signature wallet for ownership of the contract to distribute control and reduce the risk associated with a single private key compromise. For highly sensitive state transitions, consider adding a time-lock mechanism to allow the community or other stakeholders to react to proposed changes.
StatusUnresolved
Medium

Potential for Denial of Service in Transfers due to External Call Reverts

M-02The `_transfer` function calls `_liquidateTax` at its beginning. Inside `_liquidateTax`, an external call to `ITaxProcessor.processTax(taxAmount)` is made. If this external call reverts for any reason (e.g., the `taxProcessor` contract is paused, experiences an error, runs out of gas, or is malicious), the `_liquidateTax` function will revert, which in turn will cause the `_transfer` function to revert. This could effectively block all token transfers, leading to a denial of service for users.
IssueThe `_transfer` function calls `_liquidateTax` at its beginning. Inside `_liquidateTax`, an external call to `ITaxProcessor.processTax(taxAmount)` is made. If this external call reverts for any reason (e.g., the `taxProcessor` contract is paused, experiences an error, runs out of gas, or is malicious), the `_liquidateTax` function will revert, which in turn will cause the `_transfer` function to revert. This could effectively block all token transfers, leading to a denial of service for users.
FixImplement robust error handling for the external call to `ITaxProcessor.processTax`. Consider using a `try-catch` block to gracefully handle reverts from the external contract, allowing transfers to proceed even if tax processing fails. Alternatively, make the `_processTax` call an `onlyOwner` function or a function callable by anyone but with a mechanism to disable automatic liquidation if it consistently fails, preventing it from blocking all transfers.
StatusUnresolved
Low

Inefficient Loop in `initialize` for Pool Addresses

L-01The `initialize` function iterates through the `params.pools` array to set `pools[address] = true` for each address. While functional, if the `params.pools` array contains a very large number of addresses, this loop could lead to high gas costs during contract deployment or exceed block gas limits on certain networks, making initialization prohibitively expensive or impossible.
IssueThe `initialize` function iterates through the `params.pools` array to set `pools[address] = true` for each address. While functional, if the `params.pools` array contains a very large number of addresses, this loop could lead to high gas costs during contract deployment or exceed block gas limits on certain networks, making initialization prohibitively expensive or impossible.
FixFor scenarios involving a large number of pool addresses, consider implementing a separate `addPools` function that can be called multiple times by the owner after initialization, or a more gas-efficient batching mechanism that processes addresses in smaller chunks.
StatusUnresolved
Low

Hardcoded `maxSupply` as a Constant

L-02The `maxSupply` variable is declared as a `constant` with a value of `1e9 ether`. While this defines a clear maximum supply, its immutability means that the total supply can never be adjusted in the future without a full contract upgrade. This design choice removes flexibility for potential future economic adjustments, such as burning tokens to reduce supply or minting for specific purposes beyond the initial supply.
IssueThe `maxSupply` variable is declared as a `constant` with a value of `1e9 ether`. While this defines a clear maximum supply, its immutability means that the total supply can never be adjusted in the future without a full contract upgrade. This design choice removes flexibility for potential future economic adjustments, such as burning tokens to reduce supply or minting for specific purposes beyond the initial supply.
FixIf future flexibility regarding total supply is desired, consider making `maxSupply` a `public` state variable that can be set by the owner during initialization or through a governance mechanism. Alternatively, if the token is intended to be fully elastic, remove the `maxSupply` constraint entirely.
StatusUnresolved
Info

Reliance on `block.timestamp` for Time-Sensitive Logic

I-01The contract uses `block.timestamp` to calculate `taxExpirationTime` and `antiFarmerExpirationTime`. While commonly used, `block.timestamp` can be manipulated by miners within a certain range (e.g., up to 900 seconds on Ethereum, potentially more on other EVM chains) to slightly influence the timing of these events. For expiration times, the risk is generally low, but it's a known characteristic of `block.timestamp`.
IssueThe contract uses `block.timestamp` to calculate `taxExpirationTime` and `antiFarmerExpirationTime`. While commonly used, `block.timestamp` can be manipulated by miners within a certain range (e.g., up to 900 seconds on Ethereum, potentially more on other EVM chains) to slightly influence the timing of these events. For expiration times, the risk is generally low, but it's a known characteristic of `block.timestamp`.
FixBe aware of the potential for `block.timestamp` manipulation. For critical, short-duration events where precise timing is paramount, consider using `block.number` in conjunction with average block times, or external oracle solutions like Chainlink Keepers for more robust time-based execution. For expiration times, the current implementation is generally acceptable.
StatusUnresolved

Category Ratings

TechnicalLow7/10

The contract utilizes OpenZeppelin's upgradeable ERC20 and Ownable patterns, providing a solid base for code security (7.2 Code Security) and architecture (7.1 Architecture). The use of `SafeERC20` is commendable. However, a critical reentrancy vulnerability in the `_liquidateTax` function (7.2 Code Security) allows for tax bypass. Furthermore, the reliance on an external `ITaxProcessor` without robust error handling introduces a denial-of-service risk for all token transfers (7.6 External, 7.8 Operations).

GovernanceMedium6/10

The contract's economic model (7.4 Economic) is centered around dynamic tax rates and state transitions (e.g., BondingCurve, TaxEnforcedAntiFarmer). The `onlyOwner` modifier protects critical functions like `startMigration` and `finalizeMigration` (7.5 Governance, 7.3 Access Control), but this introduces a high degree of centralization risk. The hardcoded `maxSupply` limits future flexibility, and the `antiFarmerDuration` and `taxExpirationTime` rely on `block.timestamp`, which has minor manipulation risks.

UpgradesHigh3/10

The contract is designed as an upgradeable proxy using OpenZeppelin's `Initializable` pattern (7.7 Upgrades). The `initialize` function is correctly protected by the `initializer` modifier, and `_disableInitializers()` is called in the constructor to prevent re-initialization of the implementation contract. This setup adheres to standard upgradeability best practices.

Security Checklist

Contract VerifiedPass
Ownership RenouncedPass
No Mint FunctionPass
Liquidity LockedFail
Not a ProxyFail
HoneypotNoneBuy Tax0.0%Sell Tax0.0%

Proxy Upgrade Controls

Proxy TypeEtherscan Detected Custom
ImplementationVerified source

Holder Composition

4.9% in wallets20.1% in contracts
Effective Concentration12.9%

Share held by contracts — treasury, vesting, bridge or staking — is discounted against share held by wallets when the score is computed: a contract cannot decide to sell the way an anonymous holder can, though it can still be drained or voted to sell. Effective concentration is the figure the risk score is actually calculated from.

Liquidity Depth

The risk score reads depth across every pair. The volume figure and the volume-to-liquidity ratio elsewhere on this page describe only the pair this audit analysed, so the two are not directly comparable.

LP Distribution

Top-1 Unlocked Holder61.4%
Top-3 Unlocked100.0%

Key Addresses

Deployer
0x5496…cec5
Unlocked LP Held By
0x1584…cb020x14e5…be4a

No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.

What Raised This Score

  • Proxy contract (upgradeable — admin can replace logic)
  • Non-standard proxy storage (Etherscan-confirmed)
  • Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
  • LP top1 unlocked holder = 61.4% (independent LP — depth risk, pool = 99% of DEX liquidity)
  • LP top3 unlocked holders = 100.0% (independent LP — depth risk, pool = 99% of DEX liquidity)
  • Token age < 30 days (still settling)
  • 1 Critical finding(s) from audit
  • 2 Medium finding(s) from audit
  • 2 Low finding(s) from audit

Each factor is an on-chain fact recorded at the time of this analysis. The score is computed from them by a deterministic function, so the same contract returns the same score for anyone who runs the audit. How scores are computed

Related Audits

BicatHigh RiskTrust Wallet (TWT)High RiskSTABLEHigh RiskOLYHigh RiskVelvetHigh RiskUnibase (UB)High Risk

Would You Like a More Detailed Audit of b-money?

Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.

Get Detailed Audit