EVRGROW SMART CONTRACT AUDIT
Verification that contract behavior matches all published claims
renounceOwnership() on Nov 18, 2025. Tx: 0xdcedf353...87cf. No party can ever call owner-only functions again.autoBurnFees set to [100, 100, 0]. Burns reduce totalSupply directly — not a burn wallet. Max supply shrinks permanently with every trade._liquidityPending; auto-injected into the Uniswap V2 ETH pool when the threshold is reached.address(0xdead) inside _addLiquidity() — irrecoverable by design. Core initial LP separately locked via UNCX.swapThresholdRatio set to 50 (50/10000 = 0.5% of pool balance). Injection is automatic and permissionless.address(0) (burn) and the contract itself (LP). No team wallet, treasury, or marketing recipient anywhere in the code.AMMs mapping allows all 14 liquidity pools to trigger buy/sell logic correctly across Uniswap V2/V3/V4, Aerodrome, SushiSwap, PancakeSwap, Curve, Balancer/CoW Swap, and HydrexFi.Line-by-line review of all 14 source files for hidden vulnerabilities, hidden privileges, and malicious logic
_mint() call is in the constructor, minting exactly 500,000,000 tokens to the deployer. _mint() is internal in OpenZeppelin ERC20 — cannot be called externally. No public mint() function exists.assembly guard in the constructor requires the deployer to be a contract — a standard factory-deployment pattern. Ownership flows cleanly through Ownable2Step with a single owner, now the zero address.afterConstructor() uses the initializer modifier from Initializable.sol, setting _initialized = true on first call and permanently reverting any subsequent call. The router cannot be replaced post-initialization.onlyOwner — permanently frozen with renouncement. Currently excluded addresses are the deployer wallet and the contract itself, both required for correct operation.onlyOwner, permanently frozen. Additional guard: if (AMM == pairV2 || AMM == address(routerV2)) revert InvalidAMM(AMM) prevents removal of the primary pair or router._swapAndLiquify() with LP destination hardcoded to address(0xdead). Cannot drain funds — only adds more permanent liquidity.routerV2 — any other sender triggers revert CannotDepositNativeCoins. ETH received is immediately consumed in _swapAndLiquify(). No ETH withdrawal function exists._beforeTokenUpdate and _afterTokenUpdate are completely empty stubs. No hidden logic, no callbacks, no exploitable behavior._updateRouterV2(), the contract approves the Uniswap router for type(uint256).max of its own accumulated fee balance — standard for LP injection. Holders' tokens are never approved to any third party.address(this) (the contract itself), not to any external wallet. Immediately consumed in _addLiquidity()._swapping boolean mutex prevents reentrant calls during LP injection. The guard if (!_swapping && from != pairV2 && from != address(routerV2) && canSwap) ensures the swap logic cannot be triggered recursively.uint16 values with an explicit 2500 bps revert cap. Arithmetic expands to uint256 before operations. unchecked blocks in ERC20 base are guarded by explicit balance checks immediately prior.All 36 known Solidity vulnerability classes from the Smart Contract Weakness Classification registry, checked systematically against all 14 source files
| SWC ID | Vulnerability Class | Result | Notes |
|---|---|---|---|
| SWC-100 | Function Default Visibility | PASS | All functions have explicit visibility modifiers. No unintended public exposure. |
| SWC-101 | Integer Overflow and Underflow | PASS | Solidity 0.8.25 has built-in overflow protection. unchecked blocks are explicitly guarded by prior balance checks. |
| SWC-102 | Outdated Compiler Version | PASS | Uses Solidity 0.8.25 — most recent stable release at deployment. No known vulnerabilities in this version. |
| SWC-103 | Floating Pragma | PASS | Token.sol pinned at 0.8.25. OZ and Uniswap files use ^0.8.20 — acceptable for non-deployed library/interface files. |
| SWC-104 | Unchecked Call Return Value | PASS | All router calls are high-level Solidity calls that automatically revert on failure. No low-level .call() with unchecked return. |
| SWC-105 | Unprotected Ether Withdrawal | PASS | No ETH withdrawal function exists anywhere. All ETH is consumed immediately in LP injection. |
| SWC-106 | Unprotected SELFDESTRUCT | PASS | No selfdestruct instruction in any of the 14 files. |
| SWC-107 | Reentrancy | PASS | The _swapping boolean mutex prevents reentrant calls. Checks-effects-interactions pattern followed correctly. |
| SWC-108 | State Variable Default Visibility | PASS | All state variables have explicit visibility declared throughout all 14 files. |
| SWC-109 | Uninitialized Storage Pointer | PASS | No uninitialized storage pointers. All local variables are value types or explicitly initialized. |
| SWC-110 | Assert Violation | PASS | No assert() statements. Errors handled via revert with custom error types — the correct modern Solidity pattern. |
| SWC-111 | Use of Deprecated Solidity Functions | PASS | No use of suicide, throw, sha3, callcode, or other deprecated functions anywhere. |
| SWC-112 | Delegatecall to Untrusted Callee | PASS | No delegatecall anywhere in any of the 14 files. |
| SWC-113 | DoS with Failed Call | PASS | LP injection failure does not brick the contract. _swapping resets to false and operation continues normally. |
| SWC-114 | Transaction Order Dependence | INFO | LP swap is theoretically front-runnable but LP goes to address(0xdead) — no party suffers a loss. Sandwich attackers pay the 2% round-trip fee. Known and accepted trade-off in this class of auto-LP token. |
| SWC-115 | Authorization Through tx.origin | PASS | No use of tx.origin for authorization. All access control uses msg.sender via _msgSender(). |
| SWC-116 | Block Values as Proxy for Time | PASS | block.timestamp used only as deadline for Uniswap calls — standard DEX practice, not a security mechanism. |
| SWC-117 | Signature Malleability | PASS | No ECDSA signature verification in this contract. Not applicable. |
| SWC-118 | Incorrect Constructor Name | PASS | Uses the correct constructor() keyword. Legacy named-constructor vulnerability not applicable to 0.8.x. |
| SWC-119 | Shadowing State Variables | PASS | No state variable shadowing across the full inheritance chain: ERC20, ERC20Burnable, Ownable, Ownable2Step, Initializable. |
| SWC-120 | Weak Sources of Randomness | PASS | No randomness used anywhere in the contract. Not applicable. |
| SWC-121 | Missing Protection Against Signature Replay | PASS | No signature-based mechanisms in this contract. Not applicable. |
| SWC-122 | Lack of Proper Signature Verification | PASS | No signature verification in this contract. Not applicable. |
| SWC-123 | Requirement Violation | PASS | All revert conditions are logically sound and only reachable under genuinely invalid conditions. |
| SWC-124 | Write to Arbitrary Storage Location | PASS | No arbitrary storage writes. All storage access through named mappings and state variables. No pointer arithmetic. |
| SWC-125 | Incorrect Inheritance Order | PASS | Inheritance order is correct and non-conflicting. C3 linearization produces no ambiguous function resolution. |
| SWC-126 | Insufficient Gas Griefing | PASS | No relayed transactions or meta-transaction patterns that could be griefed via gas manipulation. |
| SWC-127 | Arbitrary Jump with Function Type Variable | PASS | No function type variables used anywhere in the contract. |
| SWC-128 | DoS With Block Gas Limit | PASS | No unbounded loops over dynamic arrays. All fee calculation loops are over fixed-size arrays of length 3. |
| SWC-129 | Typographical Error | PASS | Fee math reviewed carefully — no off-by-one errors, no misplaced operators. totalFees accounting is correctly structured. |
| SWC-130 | RTL-Override Control Character | PASS | Source code contains no hidden Unicode control characters or right-to-left override characters. |
| SWC-131 | Presence of Unused Variables | INFO | _beforeTokenUpdate and _afterTokenUpdate hooks are empty stubs with unused parameters. No security impact — informational only. |
| SWC-132 | Unexpected Ether Balance | PASS | Contract does not rely on address(this).balance being a specific value for any security-critical logic. |
| SWC-133 | Hash Collisions With Multiple Variable Length Args | PASS | No use of abi.encodePacked with multiple variable-length arguments. Not applicable. |
| SWC-134 | Message Call with Hardcoded Gas Amount | PASS | No .transfer() or .send() (which forward fixed 2300 gas). All ETH movement through the Uniswap router via high-level calls. |
| SWC-135 | Code With No Effects | INFO | Empty if (isAMM) { } branch inside _setAMM() is a no-op code generation artifact. No security implication. |
| SWC-136 | Unencrypted Private Data On-Chain | PASS | No sensitive data stored in private variables with any confidentiality expectation. All private state is operational. |
8 attack scenarios modeled against the contract mechanics and tokenomics
A bot observes the pending _swapAndLiquify() in the mempool, front-runs with a large ETH buy, lets the LP injection execute, then back-runs with a sell.
A front-running buy means the swap gets more ETH — benefiting the LP. LP tokens go to address(0xdead); no party suffers from unfavorable pricing. The attacker bears a 2% round-trip fee on both legs.
An adversary inflates the pool balance by adding large external liquidity, raising the threshold denominator and delaying LP injection indefinitely.
Adding liquidity benefits holders. The delay is temporary — fees continue accumulating in _liquidityPending. The public addLiquidityFromLeftoverTokens() provides a permissionless bypass path.
Use a flash loan to temporarily drain the EVRGROW/ETH pool, lowering the threshold and triggering LP injection at an artificially cheap level.
Draining the pool requires selling EVRGROW — triggering the 2% fee and burning supply. The flash loan must be repaid within the same transaction. The LP injection adds locked liquidity to address(0xdead). No value extraction path exists.
A fee-excluded address dumps large quantities of EVRGROW without incurring burn or LP fees, gaining a structural advantage over regular holders.
With ownership renounced, no new addresses can ever be fee-excluded. The two currently excluded addresses are the deployer wallet and the contract itself — both legitimate operational necessities.
A large LP holder removes liquidity from one of the 13 auxiliary pools, crashing price in that pool and creating extreme arbitrage pressure on the main pool.
The main Uniswap V2 pool's initial LP is locked via UNCX; all subsequent injections go to address(0xdead). Arbitrage between pools generates volume, triggering more burns and LP injections — reinforcing the flywheel.
_addLiquidity() uses 0 for both amountTokenMin and amountETHMin. Heavy manipulation between the swap and the add could cause value leakage.
addLiquidityETH with amountMin = 0 accepts whatever ratio the pool offers, ensuring autonomous operation always succeeds. Per-transaction LP amount is ~0.5% of pool depth, making meaningful manipulation negligible.
_swapTokensForCoin() succeeds and ETH arrives in the contract, but _addLiquidity() fails, leaving ETH permanently stranded with no recovery path.
addLiquidityETH with 0 minimums will not revert on ratio grounds. Any router-level revert rolls back the entire transaction including the swap. Even if ETH were stranded, it would be consumed on the next LP injection trigger.
An attacker controls a low-liquidity auxiliary pool and manipulates it to generate artificial buy/sell volume, gaming the burn accumulation and LP injection mechanism.
Artificial volume triggers the 2% fee split on every transaction — the attacker is net negative unless EVRGROW price appreciation from burns exceeds their 2% cost. Economically self-defeating; structurally beneficial to the protocol.
| Scenario | Attacker Profit | Protocol Impact |
|---|---|---|
| Sandwich LP swap | Negative (pays 2% fees) | Positive — LP deepens |
| Threshold griefing | Negative (adds liquidity) | Neutral / positive |
| Flash loan threshold | Negative (pays fees) | Positive — burns supply |
| Fee exclusion abuse | Not possible (renounced) | None |
| Liquidity removal | Temporary disruption only | Feeds the flywheel |
| Zero-slippage failure | Not a real failure mode | None |
| ETH stranding | Not possible | None |
| Multi-pool manipulation | Negative (pays 2%) | Positive — burns supply |
Storage layout, event completeness, deployment verification, UNCX lock, arithmetic edge cases, and pool address validation
_owner), Ownable2Step slot 1 (_pendingOwner), ERC20 slots 2–6 (_balances, _allowances, _totalSupply, _name, _symbol), Initializable slots 7–8 (_initialized, _initializing), and EVRGROW slots 9–18 (autoBurnFees through AMMs). Every contract declares storage in a distinct, non-overlapping range. No contract reads or writes a slot declared by another. C3 linearization order is correct and consistent with compiler resolution.autoBurnFeesSetup emits AutoBurnFeesUpdated; every auto-burn emits both AutoBurned and the standard ERC20 Transfer to address(0); LP injections emit LiquidityAdded; threshold changes emit SwapThresholdUpdated; fee exclusions emit ExcludeFromFees; router and AMM updates emit RouterV2Updated and AMMUpdated; Ownable2Step emits both OwnershipTransferStarted and OwnershipTransferred. One intentional omission: _liquidityPending accumulation is silent per-trade (gas optimization) but publicly readable via getAllPending(). Not a vulnerability.afterConstructor() was then called to create the Uniswap V2 pair, approve the router, and register initial AMMs — permanently locked by the initializer modifier. Additional AMMs were registered via setAMM(). Initial LP was seeded and locked on UNCX. Finally, ownership was renounced on Nov 18, 2025. The contract was fully configured and LP locked before renouncement — no window existed where it was live but unconfigured.0x2aa028...338e is locked, representing ~74.8M EVRGROW and 2.409 WETH. The lock was established Nov 18, 2025 and incrementally increased on Nov 25 and Dec 29, 2025. Note: the UNCX lock expiry is Nov 18, 2026 (one year). After that date the lock owner could withdraw the initial LP. However, all LP added by the auto-injection mechanism goes to address(0xdead) and is permanently irrecoverable regardless of the UNCX lock status. The 15.866% not in UNCX consists of LP tokens already burned on-chain via early auto-injections.amount * 200 at max realistic supply (~467M × 10¹⁸) ≈ 9.34 × 10²⁸, well within uint256 range of ~1.16 × 10⁷⁷. No overflow risk. Near-zero pool balance: getSwapThresholdAmount() returns 0, causing _swapAndLiquify to trigger with near-zero pending — a gas-wasting no-op but no security impact. Fee split rounding: with equal 100/200 split, autoBurnPortion is exactly 50% with no rounding loss at normal amounts.| Pool | Address | DEX | Status |
|---|---|---|---|
| ETH Uniswap V2 (main) | 0x2aa028...338e | Uniswap V2 | ✓ UNCX locked |
| USDC Uniswap V4 1% | 0xaa3c7f...c2ca7 | Uniswap V4 | ✓ Confirmed |
| BTC Uniswap V3 0.03% | 0xc2a517...cd1d | Uniswap V3 | ✓ Confirmed |
| ETH Aerodrome 0.3% | 0x4cfac8...5504 | Aerodrome | ✓ Confirmed |
| ETH SushiSwap V2 0.3% | 0xd863b8...fd7 | SushiSwap V2 | ✓ Confirmed |
| OHM Uniswap V2 0.3% | 0x1343a4...414 | Uniswap V2 | ✓ Confirmed |
| Zora PancakeSwap V2 | 0x38210...d0c | PancakeSwap V2 | ✓ Confirmed |
| AERO Aerodrome 0.3% | 0x86459...2c4 | Aerodrome | ✓ Confirmed |
| USDC HydrexFi 0.3% | 0x443d6...3a0 | HydrexFi | ✓ Confirmed |
| PEAS Aerodrome 0.3% | 0x1c2b8...a10 | Aerodrome | ✓ Confirmed |
| USDC Balancer/CoW | 0x10ae2...5d9 | Balancer/CoW | ✓ Confirmed |
| TOSHI Aerodrome 0.3% | 0xb9ffc...c0 | Aerodrome | ✓ Confirmed |
| cbETH/DAI Curve | 0x8b1eb...744 | Curve Finance | ✓ Confirmed |
| HYDX HydrexFi 0.3% | 0x7c556...b87 | HydrexFi | ✓ Confirmed |
Compiler settings, ERC-20 compliance, public burn exposure, and integer precision documentation
v0.8.25+commit.b61c2a91, optimizer enabled at 200 runs, EVM target: paris. The 200-run setting balances deployment cost against runtime efficiency — correct for a frequently-called contract. Known optimizer risks (YulOptimizer, StackLimitEvader) apply to contracts with deep call stacks and many local variables; EVRGROW's functions are shallow with no nested internal calls beyond super._update(). EVM target paris is well-established and stable; EVRGROW uses neither DIFFICULTY nor PREVRANDAO so the paris/shanghai distinction is irrelevant. No known Solidity 0.8.25 compiler bugs affect any pattern used in this contract.totalSupply(), balanceOf(), transfer(), transferFrom(), approve(), allowance(). Both required events (Transfer, Approval) are correctly emitted. The Approval suppression on transferFrom allowance spend is the EIP-20 permitted optimization. Fee-on-transfer behavior is correctly implemented — the contract uses swapExactTokensForETHSupportingFeeOnTransferTokens rather than the standard swap function, which is the required Uniswap variant for fee-on-transfer tokens. All public functions return correct types; OpenZeppelin always returns true on success and reverts on failure — fully EIP-20 compliant.ERC20Burnable adds two public functions. burn(value): any holder can permanently destroy their own tokens. burnFrom(account, value): a spender with granted allowance can burn from a holder's balance. Neither triggers the fee mechanism — self-burns and allowance burns are deliberate holder actions, not AMM trades, so no 1% auto-burn or LP fee fires. Neither function can be called by any party other than the token holder themselves or an explicitly approved spender. No privileged actor can burn from arbitrary wallets. Standard DeFi hygiene applies: holders should only grant allowances to contracts they trust.halfAmount = tokenAmount / 2: odd tokenAmount rounds halfAmount down; otherHalf receives the extra wei — no compounding effect. (2) autoBurnPortion = fees * 100 / 200: exactly 50% for even fees; at odd fees rounds to 0, causing the full wei to accumulate in _liquidityPending instead. (3) _liquidityPending += fees * 100 / 200: identical — rounds down by at most 1 wei for odd fees. In all cases the remainder accumulates in _liquidityPending and is included in the next LP injection. No value leaks from the system. Rounding errors are bounded, self-correcting, and negligible in aggregate.Audit Scope & Disclosure
This audit was performed by Claude (Anthropic) on May 12, 2026 based on verified source code published on BaseScan. It comprises six parts: contract behavior verification against all published claims; full backdoor analysis across all 14 source files; systematic coverage of all 36 SWC vulnerability classes; adversarial economic modeling of 8 attack scenarios; advanced checks covering storage layout, deployment sequence, UNCX lock verification, arithmetic edge cases, and independent validation of all 14 liquidity pool addresses; and supplementary checks covering compiler settings, ERC-20 standard compliance, public burn function exposure, and formal documentation of integer precision behavior. While it does not constitute a formal professional security audit — which would additionally include automated tool scanning via Slither, Mythril, or Echidna, formal mathematical verification, live fuzz testing, and multi-auditor peer review — the contract's own design substantially narrows the gap. EVRGROW has no staking logic, no governance, no oracles, no upgradeable proxy pattern, and no complex multi-contract interactions of its own design — precisely the areas where formal audits most commonly uncover critical bugs. The attack surface is genuinely narrow, and the depth of analysis performed here covers the vast majority of meaningful risk for a contract of this architecture.