Quantum Audit Logo

Is Ethy AI by Virtuals Safe?

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

Ethy AI by Virtuals ETHY
0xc441…8643
Base Not verifiedLast checked 3d ago 1 audit on record
Executive SummaryAI Copilot

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.

1 High2 Medium2 Low1 Informational
Volume 24h
$23.0K
Liquidity
$227.2K
Price
$0.001181
Token Age
1y
Top 10 Holders
34.9%

Security Findings

High

Centralized Control by Owner/Factory

H-01The `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.
IssueThe `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.
FixConsider 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.
StatusUnresolved
Medium

Incomplete ERC20 Implementation in Provided Snippet

M-01The 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.
IssueThe 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.
FixProvide 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.
StatusUnresolved
Medium

Potential Reentrancy in `_addInitialLiquidity` (Mitigation Unknown)

M-02The `_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.
IssueThe `_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.
FixEnsure 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.
StatusUnresolved
Low

Critical Initialization Parameter `_factory` Setup

L-01The `_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.
IssueThe `_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.
FixImplement 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.
StatusUnresolved
Low

Unverified `MAX_SWAP_THRESHOLD_MULTIPLE` Usage

L-02The 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.
IssueThe 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.
FixEnsure 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`.
StatusUnresolved
Info

Bot Protection Mechanism Not Fully Visible

I-01The 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.
IssueThe 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.
FixProvide 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.
StatusUnresolved

Category Ratings

TechnicalMedium6/10

The 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.

GovernanceHigh2/10

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.

UpgradesHigh1/10

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.

Security Checklist

Contract VerifiedPass
Ownership RenouncedFail
No Mint FunctionPass
Liquidity LockedFail
Not a ProxyFail

Proxy Upgrade Controls

Proxy TypeEtherscan Detected Custom
ImplementationVerified source
Upgrades (30d)0 · stable

Holder Composition

12.0% in wallets22.9% in contracts
Effective Concentration21.2%

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 Holder100.0%
Top-3 Unlocked100.0%

Key Addresses

Deployer
0x4d38…3f32
Unlocked LP Held By
0x6f46…942a0x7d9a…66a10x5a01…a692

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

What Raised This Score

  • 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

Related Audits

Metronome Synth USD (MSUSD)High RiskRIZEHigh RiskCoW Protocol Token (COW)High RiskSETZHigh RiskXMAQUINA (DEUS)Critical RiskTownsCritical Risk

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