The FlapTaxTokenV2 contract implements an upgradeable ERC20 token with advanced tax mechanisms, including anti-farmer and time-dependent taxes, and dynamic liquidation thresholds. The contract utilizes OpenZeppelin's upgradeable standards and incorporates gas optimizations. While the core tax and liquidation logic is well-structured with reentrancy guards, the high degree of owner centralization presents a significant governance risk. Minor logical inconsistencies and dependencies on external contracts for critical operations were also identified.

On-chain security analysis — is it a scam or legit?
Is 吉祥马 Safe?
Not verified
This record has not gone through deep verification and is not being monitored. The score is a dated snapshot — the token’s risk can change at any time.Own this token? Put it under verification →The FlapTaxTokenV2 contract implements an upgradeable ERC20 token with advanced tax mechanisms, including anti-farmer and time-dependent taxes, and dynamic liquidation thresholds.
Read the full analysis- Proxy contract
- Non-standard proxy storage
- Top-10 concentration > 50%
- 1 High finding(s) from audit
- 2 Medium finding(s) from audit
- 2 Low finding(s) from audit
Exact factors
- Proxy contract (upgradeable — admin can replace logic)
- Non-standard proxy storage (Etherscan-confirmed)
- Top-10 concentration > 50% (74.3% total → 62.8% effective; 55.1% in EOAs, 19.3% in contracts — heavy)
- 1 High 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
Security Checklist
as of audit · Sep 4Holders
as of audit · Sep 4, 2026- Contractstreasury, vesting, bridge, staking19.3%
- Walletsanonymous holders, free to sell55.1%
- Everyone elsethe rest of the supply25.7%
How holder types affect the score
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.
Holder balances as recorded by the audit of Sep 4, 2026
Liquidity
as of audit · Sep 4The risk score reads depth across every pair.
The LP tokens of the analysed pool are locked or burned.
0x5132…8a160x5db0…ed460xb36c…e9d30x8b92…e14f0x2341…95dd0x5658…12ab0x587b…9a5f0xf11b…18e00x8b10…ec87No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighExcessive Owner Privileges and Centralization Risk
The owner role has extensive control over critical contract parameters, including taxRate, taxDuration, antiFarmerDuration, liquidationThreshold, liqExpectedOutputAmount, quoteToken, v2Router, taxProcessor, dividendContract, and the ability to add/remove pools and manage migration states. This high degree of centralization means a single compromised owner key could lead to malicious changes, such as setting prohibitive tax rates, redirecting tax funds, or disrupting core functionality, posing a significant risk to the protocol's integrity and user funds. (7.3 Access Control, 7.5 Governance)H-01
Issue
The owner role has extensive control over critical contract parameters, including taxRate, taxDuration, antiFarmerDuration, liquidationThreshold, liqExpectedOutputAmount, quoteToken, v2Router, taxProcessor, dividendContract, and the ability to add/remove pools and manage migration states. This high degree of centralization means a single compromised owner key could lead to malicious changes, such as setting prohibitive tax rates, redirecting tax funds, or disrupting core functionality, posing a significant risk to the protocol's integrity and user funds. (7.3 Access Control, 7.5 Governance)
Fix
Implement a multi-signature wallet (e.g., Gnosis Safe) for the owner role to require multiple approvals for critical operations. For highly sensitive functions, consider adding a time-lock mechanism to allow users to react to pending changes. Explore progressive decentralization by introducing community governance for certain parameters over time.
Status
Unresolved
MediumInconsistent Initialization of taxExpirationTime
In the initialize function, poolState.taxExpirationTime is set to params.taxDuration, which is a duration in seconds. However, in finalizeMigration, this value is then updated by adding block.timestamp to convert it into an absolute timestamp. This design means taxExpirationTime stores a duration initially and only becomes an absolute timestamp after finalizeMigration is called. If finalizeMigration is significantly delayed or never called, the intended tax expiration logic could be misinterpreted or behave unexpectedly, potentially leading to taxes expiring prematurely or much later than anticipated from the initial taxDuration parameter. (7.2 Code Security)M-01
taxExpirationTimeIssue
In the initialize function, poolState.taxExpirationTime is set to params.taxDuration, which is a duration in seconds. However, in finalizeMigration, this value is then updated by adding block.timestamp to convert it into an absolute timestamp. This design means taxExpirationTime stores a duration initially and only becomes an absolute timestamp after finalizeMigration is called. If finalizeMigration is significantly delayed or never called, the intended tax expiration logic could be misinterpreted or behave unexpectedly, potentially leading to taxes expiring prematurely or much later than anticipated from the initial taxDuration parameter. (7.2 Code Security)
Fix
To improve clarity and consistency, consider initializing taxExpirationTime directly as an absolute timestamp (block.timestamp + params.taxDuration) in the initialize function if the tax is intended to start immediately upon deployment. If the tax period is meant to begin only after migration finalization, ensure this is clearly documented and that finalizeMigration is called promptly. Alternatively, rename the taxExpirationTime variable to taxDuration in initialize to accurately…
Status
Unresolved
MediumSingle Point of Failure in Tax Liquidation via v2Router
The _liquidateTax function relies on an external v2Router address (e.g., Uniswap V2 Router) to swap collected tax tokens for quoteToken. If this v2Router contract is compromised, becomes unavailable, or is maliciously upgraded (even if the owner can change it), the tax liquidation mechanism could fail. This would lead to an accumulation of tax tokens within the contract, preventing their proper processing and distribution, and potentially disrupting the token's economic model. (7.6 External)M-02
v2RouterIssue
The _liquidateTax function relies on an external v2Router address (e.g., Uniswap V2 Router) to swap collected tax tokens for quoteToken. If this v2Router contract is compromised, becomes unavailable, or is maliciously upgraded (even if the owner can change it), the tax liquidation mechanism could fail. This would lead to an accumulation of tax tokens within the contract, preventing their proper processing and distribution, and potentially disrupting the token's economic model. (7.6 External)
Fix
While the owner can update v2Router, consider implementing a fallback mechanism or a grace period for v2Router changes. Additionally, explore integrating with multiple DEX routers or a decentralized oracle for price discovery during liquidation to reduce reliance on a single external entity. Implement monitoring for v2Router functionality to detect issues promptly.
Status
Unresolved
Lowuint96 for liquidationThreshold with maxSupply Considerations
The PackedPoolState struct uses uint96 for liquidationThreshold. A custom:security-note in the code correctly highlights that if the maxSupply of the token (currently 1e9 ether) were to increase beyond ~79B ether, uint96 might not be sufficient, leading to potential overflow issues. While 1e9 ether is well within uint96 limits, this represents a future upgrade risk if the maxSupply is ever significantly increased without a corresponding adjustment to the liquidationThreshold type. (7.7 Upgrades, 7.2 Code Security)L-01
uint96 for liquidationThreshold with maxSupply ConsiderationsIssue
The PackedPoolState struct uses uint96 for liquidationThreshold. A custom:security-note in the code correctly highlights that if the maxSupply of the token (currently 1e9 ether) were to increase beyond ~79B ether, uint96 might not be sufficient, leading to potential overflow issues. While 1e9 ether is well within uint96 limits, this represents a future upgrade risk if the maxSupply is ever significantly increased without a corresponding adjustment to the liquidationThreshold type. (7.7 Upgrades, 7.2 Code Security)
Fix
Maintain vigilance regarding the maxSupply and liquidationThreshold types during any future upgrades or modifications to the token's supply. If maxSupply is ever increased beyond uint96 capacity, ensure liquidationThreshold is upgraded to a larger type (e.g., uint128 or uint256) to prevent silent overflows and maintain correct liquidation logic. Document this constraint clearly for future developers.
Status
Unresolved
LowRevert Risk from External Calls in _liquidateTax
The _liquidateTax function makes external calls to ITaxProcessor(taxProcessor).processTax and IDividend(dividendContract).trackShare. If these external contracts revert due to an error, unexpected state, or malicious design, the _liquidateTax function will also revert. Since _liquidateTax is called within the _transfer function, a failure in these external calls could prevent users from transferring tokens when the liquidation condition is met, leading to a denial of service for transfers. (7.2 Code Security, 7.6 External)L-02
_liquidateTaxIssue
The _liquidateTax function makes external calls to ITaxProcessor(taxProcessor).processTax and IDividend(dividendContract).trackShare. If these external contracts revert due to an error, unexpected state, or malicious design, the _liquidateTax function will also revert. Since _liquidateTax is called within the _transfer function, a failure in these external calls could prevent users from transferring tokens when the liquidation condition is met, leading to a denial of service for transfers. (7.2 Code Security, 7.6 External)
Fix
Consider wrapping the external calls to processTax and trackShare in try/catch blocks. This would allow the _liquidateTax function (and thus _transfer) to complete even if the external calls fail, potentially logging the error and allowing the tax tokens to accumulate for later manual processing or retry. This would prioritize token transfer availability over immediate tax processing in case of external contract issues.
Status
Unresolved
InfoRedundant IERC20 Import
The contract imports IERC20 from lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol. However, ERC20Upgradeable (which FlapTaxTokenV2 inherits from) already imports IERC20 internally. Additionally, SafeERC20 is used for external IERC20 interactions, which also handles its own IERC20 requirements. Therefore, this explicit import of IERC20 is redundant and can be removed without affecting functionality. (7.2 Code Security)I-01
IERC20 ImportIssue
The contract imports IERC20 from lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol. However, ERC20Upgradeable (which FlapTaxTokenV2 inherits from) already imports IERC20 internally. Additionally, SafeERC20 is used for external IERC20 interactions, which also handles its own IERC20 requirements. Therefore, this explicit import of IERC20 is redundant and can be removed without affecting functionality. (7.2 Code Security)
Fix
Remove the redundant `import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";` statement to clean up the code and improve readability.
Status
Unresolved
InfoMissing Zero Address Checks in Setter Functions
Several setter functions, such as setQuoteToken, setV2Router, and setTaxProcessor, do not include explicit checks to prevent setting critical addresses to address(0). While taxProcessor is checked in initialize, it can be subsequently set to address(0) by the owner. Setting these critical addresses to zero could lead to broken functionality (e.g., tax liquidation failing if v2Router or quoteToken is zero) and operational issues. (7.2 Code Security)I-02
Issue
Several setter functions, such as setQuoteToken, setV2Router, and setTaxProcessor, do not include explicit checks to prevent setting critical addresses to address(0). While taxProcessor is checked in initialize, it can be subsequently set to address(0) by the owner. Setting these critical addresses to zero could lead to broken functionality (e.g., tax liquidation failing if v2Router or quoteToken is zero) and operational issues. (7.2 Code Security)
Fix
Add require(newAddress != address(0), "Zero address not allowed") checks to setter functions for critical addresses like setQuoteToken, setV2Router, and setTaxProcessor to prevent accidental or malicious misconfiguration. For setDividendContract, where address(0) might be a valid 'no dividend' state, ensure this behavior is clearly documented.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The contract demonstrates good technical practices, including the use of OpenZeppelin upgradeable contracts and a gas-optimized PackedPoolState struct (7.1 Architecture, 7.2 Code Security). A reentrancy guard (notLiquidating) is correctly implemented for the _liquidateTax function. However, the reliance on external v2Router for liquidation introduces a dependency risk (7.6 External), and external calls within _liquidateTax could cause _transfer to revert if the called contracts fail (7.2 Code Security). A logical inconsistency in taxExpirationTime initialization was also noted (7.2 Code Security).
The contract features configurable tax rates, durations, and dynamic liquidation thresholds, providing flexibility for protocol management (7.4 Economic). However, the owner possesses extensive control over all critical parameters, including tax rates, liquidation settings, and external contract addresses (7.3 Access Control, 7.5 Governance). This high degree of centralization means the protocol's economic stability and integrity are heavily reliant on the owner's trustworthiness and the security of the owner's private key. A compromised owner could maliciously alter parameters, leading to adverse economic impacts.
The contract is designed for upgradeability using OpenZeppelin's Initializable pattern, correctly calling _disableInitializers() in the constructor and using the initializer modifier (7.7 Upgrades). This ensures a robust upgrade path. A custom:security-note within the PackedPoolState struct highlights awareness of potential storage layout issues if maxSupply were to exceed uint96 limits, demonstrating proactive consideration for future upgrades (7.7 Upgrades).
To enhance the security and decentralization of the FlapTaxTokenV2 protocol, consider implementing a multi-signature wallet or a time-locked governance mechanism for critical owner-controlled functions.
This would mitigate the risks associated with a single point of failure. Additionally, review the external dependencies for the tax liquidation process, potentially adding robust error handling or fallback mechanisms to ensure token transfers remain operational even if external calls fail.
Contract & Record
Free for any token on the record. It links to this page and always shows the current score and the date it was checked.
- Sep 4, 202644Medium
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Would You Like a More Detailed Audit of 吉祥马?
Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.
Get Detailed Audit Is this your token? Publish your own audit on this page