ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WTF Solidity 极简入门:从零手写 ERC20 代币标准并在 Remix 发行你的第一个代币

WTF Solidity 极简入门:从零手写 ERC20 代币标准并在 Remix 发行你的第一个代币 WTF Solidity 极简入门从零手写 ERC20 代币标准并在 Remix 发行你的第一个代币【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity导读本篇是 WTF Solidity 极简教程第 31 讲聚焦以太坊最基础的资产标准 ——ERC20 代币标准。文章以教程源码 31_ERC20/ERC20.sol 与 31_ERC20/IERC20.sol 为主线完整拆解标准的事件、6 个核心函数接口、全部实现细节并手把手带你在 Remix 中部署一个名为WTF的测试代币。学完本讲你将掌握从接口定义到合约实现再到链上发行的完整链路并能在后续理解水龙头Faucet、空投Airdrop等真实应用时看懂底层的approve/transferFrom授权转账机制。ERC20以太坊上的代币事实标准ERC20 是运行在以太坊上的代币标准起源于 Vitalik Buterin 在 2015 年 11 月提出的EIP20提案。它规定了代币转账所需的最基本逻辑任何遵循该标准的合约都可以被钱包、交易所和去中心化应用DApp统一识别与操作账户余额account balance每个地址持有多少代币转账transfer从调用者账户向其他账户转移代币授权转账approve transfer所有者授权第三方代扣一定额度代币总供给total token supply全网发行的代币总量代币信息可选名称name、符号symbol、小数位数decimals。ERC20 标准的意义在于接口约定只要合约实现了这些固定名称、固定输入输出参数的函数无论内部逻辑如何实现都能被整个生态无缝对接。这也是为什么项目用两个文件——接口合约IERC20.sol与实现合约ERC20.sol——来组织代码接口与实现分离前者负责对外约定共享数据与行为后者负责内部实现细节。IERC20 接口标准规定的契约接口合约interface只声明函数名、输入参数和输出参数不关心内部如何实现。IERC20规定了 2 个事件和 6 个函数见 31_ERC20/IERC20.sol。事件Event链上行为的可观测日志IERC20定义了两个事件分别在转账和授权发生时被 emit 释放event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value);Transfer当value数量的代币从from账户转移到to账户时触发。注意mint铸造与burn销毁也会释放该事件只是from或to为address(0)零地址。Approval当owner授权spender花费value数量的代币时触发。indexed关键字让事件参数可以被链下索引与检索便于钱包、区块浏览器如 Etherscan展示资产流向。函数6 个标准接口函数签名作用totalSupply()external view returns (uint256)返回代币总供给量balanceOf()external view returns (uint256)返回account账户持有的代币数量transfer()external returns (bool)从调用者账户向to转账amount代币成功返回true并释放Transfer事件allowance()external view returns (uint256)返回owner授权给spender的额度默认为 0当approve或transferFrom被调用时会变化approve()external returns (bool)调用者授权spender花费amount代币成功返回true并释放Approval事件transferFrom()external returns (bool)通过授权机制从from向to转账amount代币并从调用者的allowance中扣除相应额度释放Transfer事件function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom( address from, address to, uint256 amount ) external returns (bool);transfer/transferFrom/approve均返回布尔值表示操作是否成功totalSupply/balanceOf/allowance是view函数读取状态但不修改链上数据。手写 ERC20 实现接下来基于教程源码 31_ERC20/ERC20.sol 逐步实现接口中定义的所有功能。完整合约结构如下// SPDX-License-Identifier: MIT pragma solidity ^0.8.34; import ./IERC20.sol; contract ERC20 is IERC20 { // ... 状态变量与函数 }状态变量实现需要记录账户余额、授权额度与代币信息mapping(address uint256) public override balanceOf; // 每个地址的代币余额 mapping(address mapping(address uint256)) public override allowance; // 授权额度 uint256 public override totalSupply; // 代币总供给 string public name; // 代币名称 string public symbol; // 代币符号 uint8 public decimals 18; // 小数位数默认 18 位关键点在于balanceOf、allowance、totalSupply声明为public后编译器会自动生成同名的getter函数恰好实现了IERC20中对应的 3 个查询接口。同时给这些public变量加上override修饰符是为了覆盖override从父接口继承的同名getter例如balanceOf()函数——这是 Solidity 中用状态变量实现接口函数的标准写法。name、symbol、decimals则分别对应代币名称、符号和小数位decimals默认18即 1 个代币 10^18 个最小单位wei 量级。构造函数初始化代币名称与符号constructor(string memory name_, string memory symbol_) { name name_; symbol symbol_; }在部署合约时传入代币的名称与符号一次性写入状态变量。例如本讲部署时设置name_与symbol_均为WTF。transfer代币转账function transfer(address recipient, uint amount) external override returns (bool) { balanceOf[msg.sender] - amount; // 调用者余额减少 balanceOf[recipient] amount; // 接收者余额增加 emit Transfer(msg.sender, recipient, amount); return true; }调用者msg.sender扣减amount接收者recipient增加amount并释放Transfer事件。这是代币流通的核心。现实中不少项目会在此函数中加入税收、分红、抽奖等附加逻辑即所谓的转账即燃烧/分红模式。approve代币授权function approve(address spender, uint amount) external override returns (bool) { allowance[msg.sender][spender] amount; emit Approval(msg.sender, spender, amount); return true; }调用者将spender的可花费额度设置为amount。spender既可以是普通账户EOA也可以是合约账户。典型场景是你在 Uniswap 等 DEX 上交易代币时需要先授权代币给 Uniswap 合约DEX 才能通过transferFrom从你的账户扣款。transferFrom授权转账function transferFrom( address sender, address recipient, uint amount ) external override returns (bool) { allowance[sender][msg.sender] - amount; // 扣除调用者的授权额度 balanceOf[sender] - amount; // 发送方余额减少 balanceOf[recipient] amount; // 接收方余额增加 emit Transfer(sender, recipient, amount); return true; }授权方调用者代替sender向recipient转账amount代币同时必须扣减自己的allowance额度确保不超过授权上限。这就是 DEX、空投、批量支付等场景依赖的第三方代扣能力。mint铸造代币非标准扩展function mint(uint amount) external { balanceOf[msg.sender] amount; totalSupply amount; emit Transfer(address(0), msg.sender, amount); }铸造不在IERC20标准之内属于教程为了演示而添加的功能——任何人都可以铸造任意数量代币。从语义上看铸造等同于从零地址address(0)向调用者转账因此释放Transfer(address(0), msg.sender, amount)。真实项目中必须加入权限管理例如onlyOwner只有合约 owner 才能铸造。burn销毁代币非标准扩展function burn(uint amount) external { balanceOf[msg.sender] - amount; totalSupply - amount; emit Transfer(msg.sender, address(0), amount); }销毁调用者自己的amount代币并减少总供给等价于向零地址address(0)转账。销毁机制常见于通缩代币、回购销毁等经济模型中。实战在 Remix 中发行你的第一个代币有了ERC20标准实现在以太坊链上发行代币就非常简单了。以下是完整实操流程。第 1 步编译并部署合约在 Remix 中打开并编译ERC20.sol切到部署DEPLOY RUN TRANSACTIONS面板在构造函数参数区设置name_和symbol_均为WTF点击transact按钮完成部署部署成功后Deployed Contracts区域会出现你的ERC20合约实例一个名为WTF的代币就诞生了。第 2 步调用 mint 铸造代币在已部署合约中展开mint函数输入数量100点击mint按钮为自己铸造100个WTF代币。点击右侧 Debug 按钮查看交易日志重点关注四个关键信息Transfer事件已释放铸造来源地址0x0000000000000000000000000000000000000000零地址表示凭空铸造接收地址你的账户0x5B38Da6a701c568545dCfcB03FcB875f56beddC4铸造数量100。第 3 步用 balanceOf 验证余额在已部署合约中展开balanceOf函数输入自己的账户地址点击查询。返回结果应为100说明铸造成功。左侧面板展示账户信息与函数调用入口右侧展示函数执行详情decoded output。至此你已经完成了一次完整的代币发行部署合约 → 铸造 → 查询余额。你还可以继续用transfer向其他地址转账用approvetransferFrom体验授权转账用burn销毁代币。生产级参考OpenZeppelin 的 ERC20 实现对比教程版实现刻意保持极简便于初学者理解标准全貌。而真实项目普遍使用审计过的 OpenZeppelin 实现本仓库 lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.solv5.5.0两者对比可以清晰看到从教学实现到生产实现的差距可见性OpenZeppelin 版将_balances、_allowances、_totalSupply等状态变量设为private对外只暴露标准函数强制所有逻辑经内部函数_transfer、_approve、_mint、_burn流转错误处理教程版用-/直接运算余额不足时依赖 Solidity 0.8 的内置溢出检查回退OpenZeppelin 版则显式使用require与自定义错误ERC20InsufficientBalance等提供清晰的失败原因并且函数失败时 revert 而非返回false这是生产实现的惯例扩展机制OpenZeppelin 的ERC20是abstract合约不内置铸造/销毁而通过继承_mint/_burn让子合约自定义供给机制并遵循IERC20Metadata与IERC20Errors接口对外一致性name()、symbol()、decimals()作为view函数显式返回与教程中依赖public变量自动生成 getter 的方式殊途同归。理解两者的差异能帮助你从看懂标准进阶到写出可审计、可复用的生产代码。标准之外ERC20 在仓库中的真实应用IERC20接口在本仓库中被多处复用是后续教程的基础设施32_Faucet/Faucet.sol代币水龙头合约。requestTokens()中通过IERC20 token IERC20(tokenContract)构造接口对象调用token.balanceOf(address(this))检查水龙头余额再调用token.transfer(msg.sender, amountAllowed)向领取者发放100个代币并用requestedAddress映射限制每个地址只能领取一次——这正是 ERC20 接口抽象能力的体现只依赖接口不依赖具体实现。33_Airdrop/Airdrop.sol批量空投合约。multiTransferToken()先校验地址数组与数量数组长度一致再检查token.allowance(msg.sender, address(this)) _amountSum确认授权额度足够最后在循环中调用token.transferFrom(msg.sender, _addresses[i], _amounts[i])逐笔空投——完整演示了approve授权 →transferFrom代扣的标准用法。这些示例表明只要发行方遵循 ERC20 标准任何第三方合约钱包、DEX、水龙头、空投合约都能在不持有实现代码的情况下安全地与其交互。总结本讲从标准出发依次讲解了 ERC20 的诞生背景、IERC20接口中的 2 个事件与 6 个函数、极简实现的全部状态变量与函数细节并在 Remix 中完成了从部署、铸造到查询余额的完整代币发行流程。2015 年底提出的 ERC20 标准极大降低了在以太坊上发行代币的门槛并开启了 ICO 时代。需要提醒的是投资前务必仔细阅读项目代币合约源码——mint权限是否受控、转账逻辑是否夹带税收/黑名单、approve是否有上限等细节往往决定了代币的真实风险读懂合约是规避风险、提高投资成功率的有效手段。【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表