Appearance
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 payablewith inlined deposit logic - In
withdraw, checkrequire(balanceOf(msg.sender) >= amount)first - Use explicit
this.deposit()or write the logic directly in receive
7. Technical Highlights
| Point | Description |
|---|---|
| WETH standard | 1 ETH = 1 WETH, fully fungible |
| ERC20 inheritance | OZ ERC20 provides a complete implementation |
| receive vs fallback | receive() handles plain ETH, fallback() handles calldata |
| ETH custody security | The contract holds ETH equal to the total supply |