The AgentToken contract implements an ERC20-like token with custom tax mechanisms, bot protection, and Uniswap V2 integration. It utilizes OpenZeppelin's upgradeable patterns and a centralized access control model via an owner and a factory address. The provided code snippet is incomplete, lacking core ERC20 transfer logic and the full implementation of tax and bot protection mechanisms, which limits a comprehensive security assessment.
On-chain security analysis — is it a scam or legit?
Is Ethy AI by Virtuals 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 AgentToken contract implements an ERC20-like token with custom tax mechanisms, bot protection, and Uniswap V2 integration.
Read the full analysis- Ownership not renounced — owner is an EOA
- Proxy contract
- Non-standard proxy storage
- Top-10 concentration > 20%
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 100.0%
- LP top3 unlocked holders = 100.0%
- 1 High finding(s) from audit
- 2 Medium finding(s) from audit
- 2 Low finding(s) from audit
Exact factors
- Ownership NOT renounced — owner is an EOA (single private key)
- Proxy contract (upgradeable — admin can replace logic)
- Non-standard proxy storage (Etherscan-confirmed)
- Top-10 concentration > 20% (34.9% total → 21.2% effective; 12.0% in EOAs, 22.9% in contracts — mild)
- Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
- LP top1 unlocked holder = 100.0% (independent LP — depth risk, pool = 94% of DEX liquidity)
- LP top3 unlocked holders = 100.0% (independent LP — depth risk, pool = 94% of DEX liquidity)
- 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, staking22.9%
- Walletsanonymous holders, free to sell12.0%
- Everyone elsethe rest of the supply65.1%
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 4- Uniswap v2VIRTUALAnalysed$227.2K93.8%
- Uniswap v3USDC$9.3K3.8%
- Uniswap v3WETH$5.5K2.3%
- AerodromeWETH$2040.1%
- Uniswap v2🌙8$1090.0%
The risk score reads depth across every pair.
The LP tokens of the analysed pool are not locked or burned, so whoever holds them can withdraw that liquidity.
0x6f46…942a0x7d9a…66a10x5a01…a692No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.
Security Findings
HighCentralized Control by Owner/Factory
The onlyOwnerOrFactory modifier grants significant control over critical contract parameters to a single owner address and a single factory address. This includes setting tax rates (setProjectTaxRecipient, setSwapThresholdBasisPoints), managing liquidity pools (addLiquidityPool, removeLiquidityPool), and controlling valid callers (addValidCaller, removeValidCaller). This high degree of centralization introduces a single point of failure, making the protocol vulnerable to a compromised or malicious owner/factory.H-01
Issue
The onlyOwnerOrFactory modifier grants significant control over critical contract parameters to a single owner address and a single factory address. This includes setting tax rates (setProjectTaxRecipient, setSwapThresholdBasisPoints), managing liquidity pools (addLiquidityPool, removeLiquidityPool), and controlling valid callers (addValidCaller, removeValidCaller). This high degree of centralization introduces a single point of failure, making the protocol vulnerable to a compromised or malicious owner/factory.
Fix
Consider implementing a multi-signature wallet for the owner address to distribute control and require multiple approvals for critical operations. For the factory role, ensure the factory contract itself has robust security and access controls. Explore options for progressive decentralization over time, if aligned with the project's roadmap.
Status
Unresolved
MediumIncomplete ERC20 Implementation in Provided Snippet
The provided code snippet defines private storage variables for ERC20 (_balances, _totalSupply, _allowances, _name, _symbol) and an internal _mint function, but lacks the public transfer, transferFrom, approve, allowance, balanceOf, and decimals functions. While the contract implements IAgentToken, the actual implementation of these core ERC20 functionalities is not visible. This prevents a comprehensive security assessment of the token's fundamental transfer and approval mechanisms, which are critical for any ERC20 token.M-01
Issue
The provided code snippet defines private storage variables for ERC20 (_balances, _totalSupply, _allowances, _name, _symbol) and an internal _mint function, but lacks the public transfer, transferFrom, approve, allowance, balanceOf, and decimals functions. While the contract implements IAgentToken, the actual implementation of these core ERC20 functionalities is not visible. This prevents a comprehensive security assessment of the token's fundamental transfer and approval mechanisms, which are critical for any ERC20 token.
Fix
Provide the complete contract code, including all inherited interfaces and their implementations, especially the core ERC20 functions. A thorough review of these functions is essential to ensure they adhere to ERC20 standards and are free from vulnerabilities like reentrancy, integer overflows, or incorrect access controls.
Status
Unresolved
MediumPotential Reentrancy in _addInitialLiquidity (Mitigation Unknown)
The _addInitialLiquidity function performs external calls to _uniswapRouter.addLiquidity and IERC20(uniswapV2Pair).transfer. External calls, especially to unknown or potentially malicious contracts, can introduce reentrancy vulnerabilities if not properly guarded. While the _autoSwapInProgress flag is set to true at the start of initialize and false at the end of _addInitialLiquidity, its specific usage in preventing reentrancy during these external calls (e.g., within a _beforeTokenTransfer hook) is not visible in the provided snippet. Without the full context, a reentrancy vulnerability cannot be definitively ruled out.M-02
_addInitialLiquidity (Mitigation Unknown)Issue
The _addInitialLiquidity function performs external calls to _uniswapRouter.addLiquidity and IERC20(uniswapV2Pair).transfer. External calls, especially to unknown or potentially malicious contracts, can introduce reentrancy vulnerabilities if not properly guarded. While the _autoSwapInProgress flag is set to true at the start of initialize and false at the end of _addInitialLiquidity, its specific usage in preventing reentrancy during these external calls (e.g., within a _beforeTokenTransfer hook) is not visible in the provided snippet. Without the full context, a reentrancy vulnerability cannot be definitively ruled out.
Fix
Ensure that all external calls are protected against reentrancy. Implement a reentrancy guard (e.g., OpenZeppelin's ReentrancyGuard) on functions that make external calls, or ensure that state changes occur before external calls (Checks-Effects-Interactions pattern). Clearly document how _autoSwapInProgress prevents reentrancy in the relevant transfer hooks.
Status
Unresolved
LowCritical Initialization Parameter _factory Setup
The _factory address, which holds significant control via the onlyOwnerOrFactory modifier, is set to _msgSender() during the initialize function call. If the initialize call is made by an untrusted, incorrect, or compromised address, that address will gain broad control over the contract's critical parameters. This is a critical setup risk that could lead to unauthorized control.L-01
_factory SetupIssue
The _factory address, which holds significant control via the onlyOwnerOrFactory modifier, is set to _msgSender() during the initialize function call. If the initialize call is made by an untrusted, incorrect, or compromised address, that address will gain broad control over the contract's critical parameters. This is a critical setup risk that could lead to unauthorized control.
Fix
Implement stringent controls around the initialize function call. Ensure that only a trusted and secure entity (e.g., a deployer script controlled by a multi-sig wallet) is authorized to call initialize, and that the _msgSender() at that time is the intended factory address. Consider adding an explicit parameter for the factory address in initialize rather than relying solely on _msgSender() to prevent accidental misconfiguration.
Status
Unresolved
LowUnverified MAX_SWAP_THRESHOLD_MULTIPLE Usage
The constant MAX_SWAP_THRESHOLD_MULTIPLE is defined, likely intended to cap the swapThresholdBasisPoints to prevent excessively high swap thresholds. However, the setSwapThresholdBasisPoints function, which would enforce this cap, is truncated in the provided code snippet. Without the full implementation, it's impossible to verify if this constant is correctly utilized to prevent setting an arbitrarily high swap threshold, which could negatively impact token liquidity or user experience.L-02
MAX_SWAP_THRESHOLD_MULTIPLE UsageIssue
The constant MAX_SWAP_THRESHOLD_MULTIPLE is defined, likely intended to cap the swapThresholdBasisPoints to prevent excessively high swap thresholds. However, the setSwapThresholdBasisPoints function, which would enforce this cap, is truncated in the provided code snippet. Without the full implementation, it's impossible to verify if this constant is correctly utilized to prevent setting an arbitrarily high swap threshold, which could negatively impact token liquidity or user experience.
Fix
Ensure that the setSwapThresholdBasisPoints function correctly uses MAX_SWAP_THRESHOLD_MULTIPLE to enforce a reasonable upper limit on the swapThresholdBasisPoints. Add a require statement to validate that swapThresholdBasisPoints_ does not exceed the maximum allowed value derived from MAX_SWAP_THRESHOLD_MULTIPLE.
Status
Unresolved
InfoBot Protection Mechanism Not Fully Visible
The contract defines botProtectionDurationInSeconds and fundedDate, implying a mechanism to protect against bots, likely during the initial launch phase. However, the actual logic that enforces this protection (e.g., preventing transfers from non-liquidity pool addresses or limiting transaction sizes for a certain duration) is not provided in the snippet. This makes it impossible to assess the effectiveness, scope, or potential bypasses of the bot protection.I-01
Issue
The contract defines botProtectionDurationInSeconds and fundedDate, implying a mechanism to protect against bots, likely during the initial launch phase. However, the actual logic that enforces this protection (e.g., preventing transfers from non-liquidity pool addresses or limiting transaction sizes for a certain duration) is not provided in the snippet. This makes it impossible to assess the effectiveness, scope, or potential bypasses of the bot protection.
Fix
Provide the complete implementation of the bot protection mechanism, typically found within the _beforeTokenTransfer function. Clearly document the specific rules and conditions enforced by this mechanism, including how it interacts with different types of transfers and addresses.
Status
Unresolved
Analysis
AI Copilotas of audit · Sep 4The contract demonstrates good practices in using OpenZeppelin upgradeable components and EnumerableSet for managing dynamic lists (7.1 Architecture). Access control is robustly implemented with onlyOwnerOrFactory and Ownable2StepUpgradeable (7.3 Access Control). However, the provided code snippet is incomplete, missing core ERC20 transfer logic and the full implementation of tax and bot protection mechanisms, which prevents a complete assessment of code security (7.2 Code Security). A potential reentrancy risk exists in _addInitialLiquidity due to external calls, though its mitigation cannot be fully verified without the complete codebase.
The contract centralizes significant control over economic parameters (tax rates, recipient, swap threshold) to the owner and a factory address via the onlyOwnerOrFactory modifier (7.4 Economic, 7.5 Governance). This centralization introduces a single point of failure and potential for malicious actions or compromise. The initial setup of the _factory address is critical, as an incorrect address would gain broad control (7.8 Operations). The bot protection mechanism's full economic implications are unclear without its complete implementation.
The contract is designed for upgradeability, correctly using Initializable and _disableInitializers() in the constructor (7.7 Upgrades). It also employs Ownable2StepUpgradeable for secure ownership transfer. The use of internal for storage variables is generally good for upgradeability. However, the _factory variable is private, which is generally fine but internal is safer for storage slot consistency across upgrades if the contract were to be inherited. The absence of _authorizeUpgrade suggests it's an implementation contract, relying on a separate proxy for upgrade logic.
It is crucial to complete the ERC20 implementation and thoroughly review the _beforeTokenTransfer function, especially concerning reentrancy prevention and the bot protection mechanism.
Ensure the deployment process for initialize is secure, particularly for setting the _factory address. Consider implementing a multi-signature wallet for the owner address to mitigate centralized control risks.
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, 202669High
- Aug 16, 202660Medium
Score changes are recorded as dated snapshots — history is append-only and cannot be edited.
Frequently Asked Questions
What is the ETHY contract address?
The Ethy AI by Virtuals (ETHY) contract on Base is 0xc44141a684f6aa4e36cd9264ab55550b03c88643. Compare it with the address the project itself publishes before trading: other contracts can carry the same name and ticker.
Is Ethy AI by Virtuals a scam?
Quantum Audit's risk score for Ethy AI by Virtuals is 69/100 (High risk) as of Sep 4, 2026, computed by a deterministic function from on-chain facts — Contract verified: Verified; Ownership: Retained; Mint: No mint; Liquidity lock: Not locked; Upgradeability: Upgradeable. A score is a dated snapshot of those facts, not a guarantee; each one is listed on this page.
Is ETHY liquidity locked?
Liquidity lock: Not locked (as of Sep 4, 2026). Total DEX liquidity: $242.2K.
Who holds ETHY?
As of Sep 4, 2026, the 10 largest holders own 34.9% of the supply. The Holders section on this page shows who they are by holder type.
Would You Like a More Detailed Audit of Ethy AI by Virtuals?
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