Uniswap ERC20ETH Audit
Table of Contents
Summary
- Type
- DeFi
- Timeline
- From 2025-06-16
- To 2025-06-18
- Languages
- Solidity
- Total Issues
- 6 (6 resolved)
- Critical Severity Issues
- 0 (0 resolved)
- High Severity Issues
- 0 (0 resolved)
- Medium Severity Issues
- 0 (0 resolved)
- Low Severity Issues
- 2 (2 resolved)
- Notes & Additional Information
- 4 (4 resolved)
Scope
OpenZeppelin audited the Uniswap/ERC20-eth repository at commit 65087ac. As additional resources, the Uniswap team provided the audit team with tests and integration examples for Uniswap's Calibur to support EIP-7702 and Permit2 functionality in pull request #227 and UniswapX settlement contracts in pull request #326.
In scope was the following file:
src
└── ERC20Eth.sol
System Overview
The draft ERC-7914 standard introduces a way for approved spenders to pull native tokens from smart contract wallets or EIP-7702 delegated EOA accounts. For those wallets that are capable of executing code, arbitrary contracts can be authorized to pull native tokens from them via a new callback mechanism.
The ERC20ETH
contract leverages ERC-7914 to provide standard ERC-20 interfaces like transfer
, approve
, and transferFrom
, while managing native token balances externally. The contract inherits from Solady's ERC-20 implementation, which inherently supports EIP-2612 Permit Extension and provides infinite allowance to Uniswap's Permit2 contract.
All transferring functions have been overridden and simplified to pull native tokens (such as ETH on mainnet) from the sender via ERC-7914’s transferFromNative
function call on the sender and immediately transfer them to the intended recipient. The sender can also transfer native tokens directly via the transfer
function. Internal balance tracking has been eliminated to prevent double-entry-point balance check vulnerabilities.
The contract employs a minimal wrapper pattern to facilitate native token use within ERC-20 compatible ecosystems. It also allows smart contracts to adjust allowances for spenders via the standard approve functionality similar to ERC-20, and via the approve functionality of the Permit2
contract as it has an infinite allowance.
The permit
functionality in the contract only supports EOAs and ERC-7702 delegated EOAs while the signature validation method for smart accounts through the EIP-1271 standard is not supported. In order to support ERC20ETH token, the ERC-7914-compatible smart account must increase the allowance of the ERC20ETH
contract by calling approveFromNative
function on itself.
Security Model and Trust Assumptions
During the audit, the following trust assumptions were made:
- The ERC20ETH token is not fully ERC-20-compliant and should not be treated as such. It is a minimal wrapper to support native token transfers from ERC-7914-compatible smart accounts without the extra step of wrapping and/or unwrapping into/from WETH. As such, integrating ERC20ETH as an ERC-20 token can lead to major integration issues due to the following reasons:
- The
totalSupply
function will always return 0. - The
balanceOf
function will always revert as there is no balance tracking mechanism in the contract. - The
transfer
andtransferFrom
functions have callback mechanism to the sender viatransferFromNative
. - The
recipient
must be an EOA or a smart contract that can handle incoming ETH viareceive
orfallback
functionality.
- The
- The
ERC20ETH
contract is not supposed to hold any native tokens. Any native tokens sent to this contract can be immediately transferred by anybody. This contract only temporarily pulls native tokens from the sender and immediately sends them to the recipient. - ERC-7914-compatible smart accounts are assumed to send the exact amount of native tokens that was requested during the
transferFromNative
callback. If a greater amount is sent, the excess will remain in the contract and will be subsequently swept by any capable third party. For the same reason, no actor should ever send native tokens directly to this contract. A refund mechanism of any remaining amount might be an interesting alternative. - When pulling native tokens from an account, the contract verifies that the balance of the contract matches the expected amount to transfer. However, it does not verify the source of the funds, which can lead to
Transfer
event spoofing.
Security Considerations for Integrators
The ERC20ETH
contract essentially adds a valid ERC-20 address to represent the native token of the blockchain that it is deployed on. This creates a double entry point when referring to native tokens since many protocols use address(0)
or 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
to indicate an operation that deals with the native currency. A double entry point can turn into a double-spend vulnerability if not implemented correctly.
In addition, the transferFromNative
callback into the sender's address creates yet another re-entry or gas griefing opportunity which may not have been envisioned when designing the protocol before EIP-7702 was activated. Similarly, recipients can execute fallback mechanisms upon receiving native tokens, giving them the ability to influence transaction flow. The off-chain relayers should thoroughly take gas griefing scenarios into consideration while supporting this token through the permit
functionality or the Permit2
contract.
It is strongly advised that any integrator looking to support the ERC20ETH token in their ecosystem carefully thinks about the implications of doing so and adapts their codebase accordingly.
Low Severity
Floating Pragma
Pragma directives should be fixed to clearly identify the Solidity version with which the contracts will be compiled.
The ERC20Eth.sol
file has the solidity ^0.8.13
floating pragma directive.
Consider using fixed pragma directives for deployment. Keep in mind that starting with Solidity version 0.8.20, the PUSH0
opcode was introduced, which is still unsupported by various chains at the time of writing.
Update: Resolved in pull request #2.
Incomplete Docstrings
Within the ERC20ETH
contract, multiple instances of incomplete docstrings were identified:
- The
name
,totalSupply
, andsymbol
functions are missing the@return
tags to document their respective return values. - Within the
balanceOf
function, the unnamedaddress
parameter is not documented. However, this is reasonable because it is unused due to the function reverting unconditionally. - Within the
totalSupply
function, there is a blank line between the function definition and its associated docstrings. This will lead to parsing tools not being able to identify them.
Consider thoroughly documenting all functions and events (and their parameters or return values) that are part of a contract's public API. When writing docstrings, consider following the Ethereum Natural Specification Format (NatSpec).
Update: Resolved in pull request #2.
Notes & Additional Information
File and Contract Names Mismatch
The ERC20Eth.sol
file name does not match the ERC20ETH
contract name.
To make the codebase easier to understand for developers and reviewers, consider renaming the files to match the contract names.
Update: Resolved in pull request #4.
Missing Security Contact
Providing a specific security contact (such as an email or ENS name) within a smart contract significantly simplifies the process for individuals to communicate if they identify a vulnerability in the code. This practice is quite beneficial as it permits the code owners to dictate the communication channel for vulnerability disclosure, eliminating the risk of miscommunication or failure to report due to a lack of knowledge on how to do so. In addition, if the contract incorporates third-party libraries and a bug surfaces in those, it becomes easier for their maintainers to contact the appropriate person about the problem and provide mitigation instructions.
The ERC20ETH
contract does not have a security contact.
Consider adding a NatSpec comment containing a security contact above each contract definition. Using the @custom:security-contact
convention is recommended as it has been adopted by the OpenZeppelin Wizard and the ethereum-lists.
Update: Resolved in pull request #2.
Inconsistency in Named Return Variables
Named return variables are a way to declare variables that are meant to be used within a function's body for the purpose of being returned as that function's output. They are an alternative to explicit in-line return statements.
Throughout the codebase, named return variables are not defined except for one instance which is also unused. For instance, in ERC20Eth.sol
, the result
return variable of the totalSupply
function is unused.
Consider removing the aforementioned named return variable to ensure consistency with the design decision implemented throughout the contract for hardcoded return values.
Update: Resolved in pull request #2.
Unlicensed Code
The use of // SPDX-License-Identifier: UNLICENSED
in the code indicates that no explicit license has been specified. This has significant implications, such as:
- Restricted Usage by Default: Without a license, others are not granted permission to copy, modify, or distribute the code. Copyright laws apply by default, protecting the code, and any use without permission could be considered copyright infringement.
- Enforceability Concerns: Even though the code is legally protected, the absence of a clear license might make it harder to enforce legal rights. Some users may mistakenly believe that the code is open for use due to the lack of a license statement.
- No Attribution Requirements: Since no license is provided, there are no usage conditions such as attribution requirements. However, others are not permitted to use the code at all without explicit permission from the author.
To ensure control over how the code is used, consider specifying a license. A license provides legal protection by establishing clear usage terms which helps prevent misuse and encourages collaboration.
Update: Resolved in pull request #3.
Conclusion
This audit focused on the ERC20ETH
contract and the potential impact of integrating it into the Uniswap ecosystem. Only minor issues were identified, and several considerations were raised around the risks of incorrectly integrating the ERC20ETH token with other DeFi contracts/systems. The Uniswap team is appreciated for being highly cooperative and providing clear documentation and communication throughout the audit period.