Loading...

Loading
WalletGuard Audit: EVMBench: 2025-01-next-generation | Score: 1.0/10

high(14)

medium(11)

low(9)
Code Quality Observations(2)
Gas Optimizations(1)

Decentralization

1 centralization point identified

*
Fee is charged on transferWithAuthorization but not on forceTransfer, creating inconsistency and potential fee bypass

An ADMIN can use forceTransfer to bypass the fee mechanism. This is an admin capability that may or may not be intentional design, but represents a property of the protocol buyers should know about.

forceTransfer()

Attack Chain Analysis

Full Protocol Takeover via Unguarded setOwner and Unlimited Mintingcritical

An attacker first calls setOwner(attacker) to gain DEFAULT_ADMIN_ROLE with no access check. With DEFAULT_ADMIN_ROLE, the attacker calls setAdministrator(attacker) to gain ADMIN role, then calls setMasterMinter(attacker) and addMinter(attacker, type(uint256).max) to gain unlimited minting capability. The attacker then mints arbitrary tokens to any address, destroys token value, and can authorize a malicious UUPS upgrade via _authorizeUpgrade to permanently compromise the proxy.

setOwner lacks access control - anyone can take ownershipCritical admin functions lack access control - addController, removeController, addMinter, removeMinter, setMasterMinter are callable by anyonesetAdministrator can be called by anyone — no effective access control on ADMIN roleConstructor uses initializer modifier instead of disableInitializers()
Griefing and Operational Halt via Unguarded Controller Assignmentcritical

An attacker calls addController(attacker) with no access check to grant themselves the CONTROLLER role. They then call safetySwitch() to halt all minting and burning operations. Because _operatingController is set to the attacker's address, only the DEFAULT_ADMIN_ROLE or the attacker themselves can re-enable operations. If the attacker was also able to seize DEFAULT_ADMIN_ROLE via the unguarded setOwner, they can permanently lock the protocol. Even without owning DEFAULT_ADMIN_ROLE, the attacker can repeatedly disable and enable operations to grief the protocol.

addController and removeController lack access controlsafetySwitch can be turned off by any CONTROLLER but can only be turned back on by DEFAULT_ADMIN_ROLE or the specific controller who turned it offsetOwner lacks access control - anyone can take ownership
Fee Griefing via Pre-Signature Validation Fee Extractionhigh

In transferWithAuthorization, transferSanity is called first which invokes _payTxFee, deducting fees from the holder before signature verification occurs in the super call. An attacker can call transferWithAuthorization with any valid holder address and an invalid or replayed signature. The fee is deducted from the holder's balance, then the super call reverts due to invalid signature, but the fee payment via _update has already executed. This allows an attacker to repeatedly drain fees from any holder address.

Double fee deduction in transferWithAuthorization — fee paid twice for same transfertransferWithAuthorization nonce scheme is shared with permit, enabling cross-function replay
Meta-Transaction Domain Replay Leading to Unauthorized Transfershigh

The Forwarder accepts a caller-supplied domainSeparator without validating it against the token's actual EIP-712 domain. A malicious relayer can supply a domainSeparator from a different chain or deployment where the user previously signed a valid request. Because the nonce state may differ across deployments, a signature consumed on one chain may still be valid on another. Combined with the shared nonce namespace between permit and transferWithAuthorization, an attacker can front-run a pending transferWithAuthorization by submitting a permit with the same nonce to invalidate it, or replay a cross-domain signature via the unvalidated forwarder to execute an unauthorized transfer.

Forwarder Uses Caller-Supplied domainSeparator - No Binding to Specific Chain or ContractForwarder does not verify domainSeparator against token's domain — cross-domain replay possibletransferWithAuthorization nonce scheme is shared with permit, enabling cross-function replay

Agent Coverage

AgentStatusFindingsSeverityConfidenceDurationCoverage
reentrancysuccess11
2C1L
73%1.8mCross-function reentrancy in transfer, transferFrom, transferWithAuthorization, ERC-20 transfer hooks and callback patterns, Access control on all role-management functions, Signature verification in permit and transferWithAuthorization, Forwarder EIP-712 domain separator validation, Fee deduction logic and double-fee risks, UUPS upgrade authorization, Meta-transaction trusted forwarder security, Minting and burning access control, Blacklist and pause mechanism integrity, Integer overflow/underflow in fee calculations, CEI pattern compliance in all state-modifying functions
access controlsuccess13
2C3H1M1L
83%1.8mAccess control on all external/public functions across all files, Role management and privilege escalation paths, UUPS upgrade authorization and constructor safety, EIP-712 signature verification and replay protection in permit/transferWithAuthorization, Trusted forwarder ERC2771 meta-transaction handling, Fee calculation and deduction logic ordering, Initializer protection and initialization ordering, Ownership transfer patterns, Blacklist and pause enforcement in transfer flows, safetySwitch access control and denial-of-service vectors, Forwarder contract signature verification and domain separator handling, Cross-function interactions between fee payment and transfer execution
economicsuccess14
1H3M2L
75%2.1mAccess control on all external/public functions in ERC20ControlerMinterUpgradeable (addMinter, removeMinter, setMasterMinter, addController, removeController), UUPS upgrade authorization in Token.sol (_authorizeUpgrade), ERC2771 trusted forwarder _msgSender() override and potential spoofing, Meta-transaction signature verification in ERC20MetaTxUpgradeable (permit, transferWithAuthorization), Forwarder domain separator validation and replay protection, Fee mechanism and fee bypass paths (forceTransfer, payGaslessBasefee), Pause and blacklist enforcement in adminSanity, Role initialization with address(0) for ADMIN and MASTER_MINTER, setOwner enumerable set ordering issue, safetySwitch griefing via unguarded addController, Flash loan attack surface (no token balance-based pricing, not applicable), Oracle manipulation (no price feeds present, not applicable), Governance token flash loan attacks (not applicable — no governance token voting), Reentrancy in _update, _mint, _burn paths, Integer overflow/underflow (Solidity 0.8.20 with built-in checks), Fee-on-transfer token accounting (not applicable — this IS the token), MEV/sandwich exposure on transfers
logic validationsuccess12
2H1M1L
79%2.0mInput validation on all public/external functions, Role-based access control on admin functions (setAdministrator, setOwner, setMasterMinter, addMinter, addController), Integer arithmetic in fee calculations, State machine integrity for safetySwitch and operating state, EIP-712 domain separator construction and signature verification in permit/transferWithAuthorization, Forwarder signature verification and replay protection, Fee deduction ordering relative to transfer execution, transferWithAuthorization ordering of sanity checks vs signature verification, UUPS upgrade authorization, Meta-transaction trusted forwarder pattern, AccessControlEnumerable index-0 ordering issues in role transfers, Dead code checks (uint < 0), ETH handling in Forwarder, Blacklist bypass scenarios for admin
code qualitysuccess16
1C1M
83%2.2mAccess control on all external/public functions, Role initialization and management (ADMIN, MASTER_MINTER, MINTER_ROLE, CONTROLLER, OWNER), ERC-20 transfer, transferFrom, approve, permit compliance, ERC-2612 permit standard compliance, Meta-transaction trusted forwarder security, Fee-on-transfer logic and atomicity, UUPS upgrade authorization, Safety switch mechanism, Blacklist enforcement in transfer paths, Forwarder signature verification, Integer overflow/underflow (Solidity 0.8.20), Reentrancy in transfer flows, Storage collision in upgradeable contracts, Dead code analysis, Gas optimization opportunities
compiler bugssuccess8
1H1L
85%1.4mAccess control on all external/public functions across all contracts, Role management logic in ERC20AdminUpgradeable and ERC20ControlerMinterUpgradeable, Signature verification in ERC20MetaTxUpgradeable (permit, transferWithAuthorization), Forwarder signature verification and domainSeparator handling, ERC2771 trusted forwarder implementation and _msgSender override, Fee calculation and payment logic in FeesHandlerUpgradeable and Token.sol, UUPS upgrade authorization, Reentrancy in transfer/mint/burn flows, Integer overflow/underflow (Solidity 0.8.20 has built-in checks), Blacklist bypass vectors, safetySwitch logic and controller role permissions, setOwner ordering and race conditions, Compiler bug patterns (pragma ^0.8.20 - outside all affected ranges), Storage collision in UUPS proxy pattern, Initializer security and constructor usage
assembly safetysuccess15
4H1M
85%2.1mFull codepoint scan for non-ASCII characters (RTLO, zero-width, homoglyphs) in all identifiers, strings, and comments, Assembly blocks: _msgSender() ERC2771 assembly in ERC20MetaTxUpgradeable — checked for calldataload offset correctness and shr argument order, Access control on all externally/publicly callable functions across all files, Role initialization patterns and address(0) role grants, UUPS upgrade authorization path, Fee calculation and double-deduction analysis in transfer/transferFrom/transferWithAuthorization, Signature authentication in permit and transferWithAuthorization including nonce sharing, Trusted forwarder ERC2771 _msgSender() manipulation path, safetySwitch logic and operating state management, setOwner ownership transfer logic and missing access control, Storage gap analysis for upgradeable contracts, forceTransfer admin bypass logic, Cross-function reentrancy (no external calls in transfer paths except _update which is internal), Integer overflow/underflow (Solidity 0.8.20, checked arithmetic), Delegatecall patterns in UUPS proxy, Keyword obfuscation and lookalike identifiers
l2 specificsuccess12
3H3M2L
77%1.7mAccess control on all public/external functions across all files, Role initialization patterns (address(0) role grants), UUPS upgrade authorization path, ERC2771 trusted forwarder implementation and _msgSender override, Fee calculation and payment logic (double-fee potential), Transfer functions: transfer, transferFrom, transferWithAuthorization, Permit/EIP-712 signature verification, Blacklist and pause enforcement logic, safetySwitch controller logic, Forwarder signature verification and domain separator handling, Minting allowance management and enforcement, setOwner and setAdministrator ownership transfer logic, Integer overflow/underflow in fee calculations, Reentrancy in transfer paths (no external calls before state updates in critical paths), Cross-contract interaction between Forwarder and EURFToken, MASTER_MINTER and ADMIN role bootstrap with address(0)
upgradesuccess14
1M
78%2.6mUUPS upgrade pattern and _authorizeUpgrade protection, Constructor initializer pattern vs _disableInitializers(), Storage layout across all inherited contracts for gaps and potential collisions, Access control on all external/public functions across all contracts, Role management (grantRole/revokeRole ordering bugs), Meta-transaction trusted forwarder pattern and _msgSender() override, EIP-712 permit and transferWithAuthorization signature verification, Fee calculation and payment logic, Blacklist and pause enforcement across transfer paths, Forwarder signature verification and domain separator handling, Minting/burning allowance enforcement, safetySwitch emergency stop logic, Cross-function reentrancy in transfer flows, Integer overflow/underflow in fee calculations, Storage slot collision between proxy ERC-1967 slots and contract storage

Scope and Methodology

Target0x4508a4b2caeba174883dddf1e2686ee7ffb23e88
ChainEthereum
Proxy Patternuups
Complexitycomplex
Standards DetectedERC20, ERC2771
Analysis ModelClaude Sonnet 4.6
Specialist Agents10
Agent Types
reentrancyaccess controleconomiclogic validationcode qualitycompiler bugsassembly safetyl2 specificupgrade
Scope TemplateGeneral Smart Contract (auto-selected)
MethodologyAutomated multi-agent analysis. Each specialist agent independently reviews the contract source code for vulnerabilities in its domain. Findings are deduplicated, scored, and synthesized into this report.
Findings are gated by demonstrated exploit feasibility against the analyzed contract. Observations that describe accepted blockchain behavior, consensus-layer issues, or infeasible preconditions are excluded from scored findings. See scope policy.

Severity Classification

CriticalDirect loss of funds or complete protocol compromise. Exploitable with high likelihood. Requires immediate remediation.
HighSignificant risk to funds or protocol integrity. Conditionally exploitable or requires specific circumstances. Should be fixed before deployment.
MediumLimited or conditional impact. May require unlikely conditions to exploit. Should be addressed but not blocking.
LowMinor impact. Best practice deviations, minor inefficiencies. Fix when convenient.
InformationalNo direct security impact. Code quality observations, gas optimizations, style recommendations.

Limitations

This automated audit has inherent limitations. The following areas are not covered.

Disclaimer

This report is an automated point-in-time assessment and does not guarantee protection against all possible attacks. It does not cover off-chain components, economic modeling, or business logic correctness unless explicitly noted. Changes to the contract after the audit commit are not reviewed. This is not financial or legal advice. WalletGuard, powered by Gestalt Labs, provides this analysis as-is with no warranty of completeness.

Embed Badge
WalletGuard Audit Badge
Markdown
[![WalletGuard Audit](https://walletguard.ai/api/badge/0b5a7cf2-876b-46bd-ac46-8c0f9e9e0851)](https://walletguard.ai/audit/0b5a7cf2-876b-46bd-ac46-8c0f9e9e0851)
HTML
<a href="https://walletguard.ai/audit/0b5a7cf2-876b-46bd-ac46-8c0f9e9e0851">
  <img src="https://walletguard.ai/api/badge/0b5a7cf2-876b-46bd-ac46-8c0f9e9e0851" alt="WalletGuard Audit Badge" />
</a>
WalletGuardSecured by WalletGuard
How We AuditView all reports for this contractUID: 0x9f2e4368...a1496bThis report was produced by generic vulnerability pattern matching.
Modelsonnet
Duration5.8m
CostN/A
Tokens- in / - out
Source verified via Etherscan