Skip to content
On this page

L1-5: Token Wrapper (WETH)

1. Problem

Create an ERC20-compatible wrapper token for ETH. Users deposit ETH to receive WETH, and burn WETH to withdraw ETH, at a 1:1 exchange rate.

2. Why

Native ETH does not conform to the ERC20 standard and cannot directly interact with DeFi protocols. WETH serves as an ERC20 equivalent of ETH:

  • All DeFi protocols use the same interface to handle tokens
  • ETH holders can participate in AMMs, lending, and other protocols
  • Protocols do not need special handling for native ETH

3. Solution

Inherit OpenZeppelin ERC20

solidity
contract WrappedETH is ERC20("WrappedEth", "WETH")

Core Functions

  • deposit() payable: ETH → WETH (mint)
  • withdraw(uint256): WETH → ETH (burn + transfer)
  • receive(): auto deposit

4. Pitfalls Encountered

4.1 Direct ETH transfers are ignored

Without implementing receive(), users sending ETH directly to the contract will be rejected or silently lost.

4.2 Function name conflicts with event name

The deposit function name and Deposit event name can cause ambiguity in Solidity. When calling deposit() inside receive(), the compiler may raise an error.

4.3 Insufficient balance not checked

Not checking the balance in withdraw will cause the burn to fail.

5. Why the Pitfalls Happen

5.1

Contracts without receive() revert when receiving ETH. Users who forget to call deposit() and send ETH directly will have their transaction fail.

5.2

When calling deposit() inside the receive function, the Solidity compiler may resolve deposit as a reference to the Deposit event rather than the function. Use this.deposit() or inline the logic.

5.3

OZ ERC20's _burn checks the balance, but not checking at the withdraw entry first could waste gas on a failed burn.

6. How to Resolve the Pitfalls

  • Implement receive() external payable with inlined deposit logic
  • In withdraw, check require(balanceOf(msg.sender) >= amount) first
  • Use explicit this.deposit() or write the logic directly in receive

7. Technical Highlights

PointDescription
WETH standard1 ETH = 1 WETH, fully fungible
ERC20 inheritanceOZ ERC20 provides a complete implementation
receive vs fallbackreceive() handles plain ETH, fallback() handles calldata
ETH custody securityThe contract holds ETH equal to the total supply

Built with AiAda