尧图精选

WTF-Solidity 第 41 讲:WETH 合约实战——用 Solidity 0.8 重新实现封装 ETH(Wrapped ETH)

🕒 发布时间:2026/9/15 17:44:59 📁 来源:尧图网络
WTF-Solidity 第 41 讲WETH 合约实战——用 Solidity 0.8 重新实现封装 ETHWrapped ETH【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity导读本文基于 WTF-Solidity 极简入门教程的第 41 讲对应仓库Languages/pt-br/41_WETH/readme.md与中文原版 41_WETH/readme.md系统讲解WETHWrapped ETH封装以太币的设计动机、合约源码与 Remix 实操全流程。读者将掌握为什么原生 ETH 不满足 ERC20 标准、包装/拆包装deposit/withdraw如何实现 1:1 兑换、fallback()/receive()回调如何把直接转账 ETH自动变成存款以及如何用 Solidity 0.8 与 OpenZeppelin ERC20 依赖完整重写一个生产可用风格的WETH合约。什么是 WETH为什么要包装原生代币WETHWrapped ETH是ETH的带包装版本。我们在链上常见的WETH、WBTC、WBNB都属于带包装的原生代币wrapped native token。一切源于 2015 年诞生的 ERC20 代币标准。该标准为以太坊上的代币制定了一套标准化规则统一了transfer、approve、transferFrom、balanceOf等接口与Transfer、Approval事件从而简化新代币的发布并让链上所有同质化代币可以互相比较、组合、交易。然而遗憾的是以太币本身并不符合 ERC20 标准——它是协议层原生资产没有合约地址无法被普通的 ERC20 钱包、去中心化交易所DEX与 DeFi 协议当作标准代币统一处理。WETH的开发正是为了提高区块链之间的互操作性interoperability让ETH可以被去中心化应用程序dApps直接使用。形象地说WETH就像给原生代币穿了一件智能合约做的衣服穿上衣服时它变成WETH符合 ERC20 同质化代币标准可以跨链、可以进入 dApp 生态脱下衣服时它可以按1:1 比例换回ETH。包装与拆包装完全可逆价值始终锚定。WETH 合约从 0.4 老合约到 0.8 重写目前在主网广泛使用的 WETH 合约写于 2015 年当时 Solidity 还是 0.4 版本代码风格与今天差异很大。本教程用Solidity 0.8重写了一个简洁清晰的WETH源码见仓库 41_WETH/WETH.sol该文件声明pragma solidity ^0.8.34并 import OpenZeppelin 的 ERC20 依赖。WETH完全符合 ERC20 标准比普通 ERC20 代币多出两个核心功能存款包装用户将ETH存入WETH合约获得等量的WETH取款拆包装用户销毁WETH获得等量的ETH。完整合约代码如下// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import openzeppelin/contracts/token/ERC20/ERC20.sol; contract WETH is ERC20{ // 事件存款和取款 event Deposit(address indexed dst, uint wad); event Withdrawal(address indexed src, uint wad); // 构造函数初始化ERC20的名字和代号 constructor() ERC20(WETH, WETH){ } // 回调函数当用户往WETH合约转ETH时会触发deposit()函数 fallback() external payable { deposit(); } // 回调函数当用户往WETH合约转ETH时会触发deposit()函数 receive() external payable { deposit(); } // 存款函数当用户存入ETH时给他铸造等量的WETH function deposit() public payable { _mint(msg.sender, msg.value); emit Deposit(msg.sender, msg.value); } // 提款函数用户销毁WETH取回等量的ETH function withdraw(uint amount) public { require(balanceOf(msg.sender) amount); _burn(msg.sender, amount); payable(msg.sender).transfer(amount); emit Withdrawal(msg.sender, amount); } }继承站在 ERC20 标准之上WETH符合 ERC20 代币标准因此直接contract WETH is ERC20继承 OpenZeppelin 的 ERC20 合约自动获得name()、symbol()、decimals()、totalSupply()、balanceOf()、transfer()、approve()、transferFrom()等全部标准能力。在仓库中该依赖对应 lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol构造函数接收name_与symbol_两个参数并将其写入不可变状态变量见该文件 ERC20.sol#L44-L47这里传入的都是WETH。事件存款与取款的链上凭证WETH合约共定义 2 个事件见 WETH.sol#L9-L10Deposit(address indexed dst, uint wad)存款事件在存款时释放dst为存款人wad为金额Withdrawal(address indexed src, uint wad)取款事件在取款时释放src为取款人。indexed关键字让这两个地址参数可以被链下索引器高效检索前端与浏览器可以据此监听、统计每一笔包装/拆包装操作。函数5 个关键入口除了 ERC20 标准函数外WETH合约共有 5 个函数见 WETH.sol#L13-L37构造函数constructor() ERC20(WETH, WETH)初始化 ERC20 代币的名字与代号二者均为WETHfallback()回退函数。当用户直接向合约转账ETH且 calldata 为空或无法匹配任何函数时触发内部自动调用deposit()把本次转入的 ETH 立即包装成 WETHreceive()接收函数。当用户只发送ETH空 calldata时触发同样自动调用deposit()。fallback()与receive()双保险覆盖了所有直接转 ETH的场景deposit()存款函数public payable。将msg.value的 ETH 收下并通过_mint(msg.sender, msg.value)给调用者铸造等量 WETHwithdraw(uint amount)取款函数。先require校验调用者 WETH 余额足够再_burn销毁对应数量的 WETH最后用payable(msg.sender).transfer(amount)返还等量 ETH。源码级原理deposit 与 withdraw 如何保证 1:1deposit收 ETH铸 WETHdeposit()是纯铸造逻辑function deposit() public payable { _mint(msg.sender, msg.value); emit Deposit(msg.sender, msg.value); }msg.value是调用者本次随交易发送的 ETH 数量以 wei 为单位与 ERC20 的 18 位小数精度天然对齐_mint是 OpenZeppelin ERC20 的内部函数见 ERC20.sol#L214-L219它调用_update(address(0), account, value)从零地址转出即代表增发_totalSupply累加、接收方余额累加并释放Transfer事件见 ERC20.sol#L176-L204由于铸造量严格等于收到的 ETH 数量WETH的总供应量始终等于合约中锁定的 ETH 总量从供给端保证了 1:1 兑换关系emit Deposit(...)记录这笔存款方便链下追踪。withdraw烧 WETH退 ETHwithdraw()是铸币的逆操作function withdraw(uint amount) public { require(balanceOf(msg.sender) amount); _burn(msg.sender, amount); payable(msg.sender).transfer(amount); emit Withdrawal(msg.sender, amount); }require(balanceOf(msg.sender) amount)前置校验余额不足直接回滚杜绝超支_burn见 ERC20.sol#L229-L234通过_update(account, address(0), value)销毁代币余额扣减、_totalSupply减少、释放Transfer事件payable(msg.sender).transfer(amount)以转账方式返还 ETH。transfer内置 2300 gas 上限调用方如果是合约则需注意该限制这是教程版本为保持极简而采用的写法生产环境也可改用call并做重入防护销毁量与返还量相等总供应量再次回落合约锁定的 ETH 与流通 WETH 始终匹配。fallback / receive让直接转账等于自动存款fallback() external payable { deposit(); } receive() external payable { deposit(); }这是WETH最巧妙的设计用户无需调用任何函数只要向 WETH 合约地址直接转 ETHreceive()纯转账或fallback()带数据就会被触发自动执行deposit()完成包装。这意味着任何支持往地址转 ETH的钱包都能无感知地把 ETH 变成 WETH极大降低了使用门槛。Remix 实操演示下面按教程原始演示步骤在 Remix 中完整走一遍 WETH 的包装与拆包装流程。前提先部署一个 ERC20 版WETH合约源码即上文代码可在 Remix 中新建文件后粘贴编译部署。第 1 步部署 WETH 合约编译通过后部署WETH合约部署完成后合约面板会展示全部 ERC20 标准函数以及新增的deposit、withdraw。第 2 步调用 deposit 存入 1 ETH查看 WETH 余额在deposit函数的 Value 栏填入1 ETH并调用调用成功后调用balanceOf并传入自己的地址可看到 WETH 余额为1 WETH因为精度 18 位显示为1000000000000000000第 3 步直接向 WETH 合约转账 1 ETH验证自动存款不调用任何函数直接在转账面板把1 ETH发送到 WETH 合约地址由于receive()的存在这 1 ETH 会被自动执行deposit()。再次调用balanceOf查看余额WETH 余额已变为2 WETH这一步直观验证了直接转账 自动包装的设计。第 4 步调用 withdraw 取出 1.5 ETH查看 WETH 余额调用withdrawamount填1500000000000000000即 1.5 WETH交易成功后调用balanceOf查看余额WETH 余额变为0.5 WETH同时账户收到了等量的 1.5 ETH演示小结步骤操作合约行为WETH 余额变化1部署合约初始化 name/symbol 为 WETH0 → 02deposit存入 1 ETH铸造 1 WETH0 → 13直接转账 1 ETHreceive()触发自动存款铸造 1 WETH1 → 24withdraw(1.5)销毁 1.5 WETH 并返还 1.5 ETH2 → 0.5整个流程中合约锁定的 ETH 与流通中的 WETH 始终严格 1:1没有任何凭空铸造或丢失。从仓库看 WETH 的工程化细节Solidity 版本仓库内的 41_WETH/WETH.sol 实际使用pragma solidity ^0.8.34并 importopenzeppelin/contracts/token/ERC20/ERC20.sol依赖由仓库 lib/openzeppelin-contractsv5.5.0提供其中_mint/_burn均通过统一的_update记账内核实现事件、余额、总供应量在单一入口完成一致性更新教程定位本讲与仓库中的 31_ERC20ERC20 标准实现、19_Fallbackfallback/receive 机制、20_SendETHtransfer/send/call 三种转账方式互为补充建议按序学习以理解 WETH 的全部底层依赖多语言版本本文对应仓库的葡萄牙语版 Languages/pt-br/41_WETH/readme.md、英语版 Languages/en/41_WETH_en 与中文原版三份文档结构与演示截图一致可对照阅读。总结这一讲介绍了WETH并完整实现了WETH合约。它就像给原生ETH穿了一件智能合约做的衣服穿上衣服时变成符合 ERC20 同质化代币标准的WETH可以跨链、可以用于 dAppDEX、借贷、衍生品等 DeFi 场景全部依赖这种包装脱下衣服时可以按 1:1 比例换回ETH。核心机制只有两个函数——deposit()收 ETH 铸 WETH、withdraw()烧 WETH 退 ETH加上receive()/fallback()的自动存款魔法这就是以太坊生态中最基础也最重要的接口适配层合约。【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →