imtoken苹果手机怎么下载|erc20是什么缩写
imtoken苹果手机怎么下载|erc20是什么缩写
什么是ERC-20? - 知乎
什么是ERC-20? - 知乎切换模式写文章登录/注册什么是ERC-20?穆逸扬Myytydy用注意力写作,用比特币存钱摘要简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币;我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献,也是以太坊网络第一个真正意义上的杀手级应用。以下是正文这次的更新我们来聊聊ERC-20这个你很可能听过,但大概率一知半解的区块链“黑话”。如果你是定投人生课堂的成员,或者正在践行定投区块链数字资产的策略,相信ERC-20这个词对你而言一定不陌生。ERC-20的定义如同CoinDesk专栏作者 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中所说的:ERC-20以太坊代币标准是创建与更广泛的以太坊网络兼容的可替换代币的蓝图。以太坊,或称Ethereum,是一种加密货币,允许创建各种应用,包括代币,与大多数传统应用不同,它不需要中心化服务机构就可以运作。上面引述的内容可能不太好理解,简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。其中的ERC是"EthereumRequest for Comment"也就是“以太坊征求意见协议”的缩写。和其他的开源社区一样,以太坊会使用这样的方式收集开发者的反馈、并在批准后作为后续开发的执行标准。ERC-20的价值和影响毫无疑问,ERC-20是所有ERC协议中最广为人知的一个。我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献(此处完全可以去掉“之一”,我甚至不介意再去掉“早期”)。是的,在我看来ERC-20就是以太坊网络第一个真正意义上的杀手级应用。正是因为有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币。也正是这一协议提供的这种极大的便利,使得首次代币发行,也就是大名鼎鼎同时饱受争议的ICO,能一度在区块链世界大行其道——助长大量骗局的同时,也在客观上推动了区块链相关技术与应用的爆发式增长。更有趣的是,ERC-20的火爆甚至直接催生了一些类似TRC-20这样,连协议的数字代号都懒得改一下的像素级山寨竞品。一个便于理解的类比如果上面的这些叙述还是让你一知半解,甚至完全摸不到头脑,我们不妨打个容易理解的比方:如果我们把众多区块链项目的开发者,看作是在一个小区门口商铺里,经营不同业态的众多商户。这些商户根据自己的专长提供各自不同的商品和服务,也都希望发行自己店铺专属的消费储值卡。方便消费者光顾的同时,也能提升用户的体验和粘性。以太坊就像是运营这个小区底商的物业公司,它提供一整套标准化的储值卡发放协议和配套服务。借助这套叫做ERC-20的整体解决方案,每个商户(开发者)都可以傻瓜式地发行专属于自己店铺的消费储值卡,同时由于这种储值卡采用了统一的协议,可以非常方便地和其他商户的储值卡做无缝兑换。于是借助ERC-20,用户可以通过持有其中一种储值卡(token)很方便地享受整个生态的各种服务;商户(开发者)则节约了开发运营成本、同时提升了获取用户的效率;而物业公司(以太坊基金会和矿工)则可以通过做大生态体量实现更多的租金(ETH增值)和储值卡结算手续费(Gas费用)收入。ERC-20就是用这种做大生态价值的方式,实现了用户、开发者和以太坊网络三方面的共赢。ERC-20的应用案例为了让你对ERC-20有更具象化的认识,这里援引 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中列举的一些比较知名的基于ERC-20协议代币:Tether (USDT)Chainlink (LINK)Binance coin (BNB)USD coin (USDC)Wrapped bitcoin (WBTC)Dai (DAI)需要特别指出的是,这上面提到的Tether发行的稳定币USDT除了基于ERC-20协议的版本之外,其实还有基于其他公链发行的多个版本,只不过ERC-20版的发行量最大,知名度也最高。ERC-20与BOX的关系ERC-20版本的USDT,在我们定投人生课堂的战友定投BOX的过程中,也有很广泛的应用。比如通过ExinOne(Mixin ID:7000101276),可以轻松实现存USDT自动执行每周/每日定投BOX的操作。说到BOX这个区块链数字资产开源配方,它和ERC-20的关系也十分密切——其中的两个成分,XIN、UNI就是基于ERC-20协议发行的代币,此外BOX本身同样是一个基于此协议发行的Token——可以说,如果没有ERC-20,BOX这个区块链数字资产开源配方就不会是现在这个样子了。参考内容What is the ERC-20 Ethereum Token Standard?ERC 协议终极解读:ERC-20你常听到的 ERC20 和 ERC721 到底是什么?一文弄懂什么是 ERC20BOX简介发布于 2021-12-02 16:01虚拟货币区块链(Blockchain)ethereum赞同 5添加评论分享喜欢收藏申请
ERC20解读 | 登链社区 | 区块链技术社区
ERC20解读 | 登链社区 | 区块链技术社区
文章
问答
讲堂
专栏
集市
更多
提问
发表文章
活动
文档
招聘
发现
Toggle navigation
首页 (current)
文章
问答
讲堂
专栏
活动
招聘
文档
集市
搜索
登录/注册
ERC20解读
Confucian
更新于 2022-04-04 19:54
阅读 6964
对ERC20代币标准的个人解读
# ERC20解读
**参考 **[**OpenZepplin文档**](https://docs.openzeppelin.com/contracts/4.x/erc20)** 和 **[**以太坊官方开发者文档**](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)**,结合自己的理解。**
博客的 Markdown 编辑器暂不支持 Solidity 语法高亮,为了更好阅读代码,可以去 [**我的GitHub仓库**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/tree/main/ERC20) 。
## **什么是ERC20**
**ERC20(Ethereum Request for Comments 20)一种代币标准。**[**EIP-20**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 中提出。
**ERC20 代币合约跟踪同质化(可替代)代币:任何一个代币都完全等同于任何其他代币;没有任何代币具有与之相关的特殊权利或行为。这使得 ERC20 代币可用于交换货币、投票权、质押等媒介。**
## **为什么要遵守ERC20**
**EIP-20 中的动机:**
> **允许以太坊上的任何代币被其他应用程序(从钱包到去中心化交易所)重新使用的标准接口。**
**以太坊上的所有应用都默认支持 ERC20 ,如果你想自己发币,那么你的代码必须遵循 ERC20 标准,这样钱包(如MetaMask)等应用才能将你的币显示出来。**
## **代码实现**
**需要实现以下函数和事件:**
```
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
```
**使用 OpenZeppllin 提供的库能够轻松快速地构建 ERC20 Token 。**
### **快速构建**
**这是一个 GLD token 。**
```
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
```
**通常,我们定义代币的发行量和代币名称及符号。**
### **IERC20**
**先来看下 ERC20 的接口(IERC20),这方便我们在开发中直接定义 ERC20 代币。**
**同样地,OpenZepplin 为我们提供了相应的库,方便开发者导入即用。**
```
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
```
****EIP 中定义的 ERC20 标准接口:****
```
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
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);
}
```
#### **逐一分析**
**函数:**
* `totalSupply()` :返回总共的代币数量。
* `balanceOf(address account)` :返回 `account` 地址拥有的代币数量。
* `transfer(address to, uint256 amount)` :将 **`amount`** 数量的代币发送给 **`to`** 地址,返回布尔值告知是否执行成功。触发 **`Transfer`** 事件。
* `allowance(address owner, address spender)` :返回授权花费者 **`spender`** 通过 **`transferFrom`** 代表所有者花费的剩余代币数量。默认情况下为零。当 **`approve`** 和 **`transferFrom`** 被调用时,值将改变。
* `approve(address spender, uint256 amount)` :授权 **`spender`** 可以花费 **`amount`** 数量的代币,返回布尔值告知是否执行成功。触发 **`Approval`** 事件。
* `transferFrom(address from, address to, uint256 amount)` :将 **`amount`** 数量的代币从 **`from`** 地址发送到 **`to`** 地址,返回布尔值告知是否执行成功。触发 **`Transfer`** 事件。
**事件(定义中的 **`indexed`** 便于查找过滤):**
* `Transfer(address from, address to, uint256 value)` :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
* `Approval(address owner, address spender, uint256 value)` :当代币所有者授权别人使用代币时触发,即调用 **`approve`** 方法。
#### **元数据**
**一般除了上述必须实现的函数外,还有一些别的方法:**
* `name()` :返回代币名称
* `symbol()` :返回代币符号
* `decimals()` :返回代币小数点后位数
### **ERC20**
**来看下 ERC20 代币具体是怎么写的。**
**同样,OpenZepplin 提供了现成的合约代码:**
```
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
```
这里贴一个GitHub源码链接 [**OpenZepplin ERC20**](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
#### **函数概览**
```
constructor(name_, symbol_)
name()
symbol()
decimals()
totalSupply()
balanceOf(account)
transfer(to, amount)
allowance(owner, spender)
approve(spender, amount)
transferFrom(from, to, amount)
increaseAllowance(spender, addedValue)
decreaseAllowance(spender, subtractedValue)
_transfer(from, to, amount)
_mint(account, amount)
_burn(account, amount)
_approve(owner, spender, amount)
_spendAllowance(owner, spender, amount)
_beforeTokenTransfer(from, to, amount)
_afterTokenTransfer(from, to, amount)
```
****事件(同 IERC20)****
```
Transfer(from, to, value)
Approval(owner, spender, value)
```
#### **逐一分析**
* `constructor(string name, string symbol)` :设定代币的名称和符号。**`decimals`** 默认是 18 ,要修改成不同的值你应该重载它。这两个值是不变的,只在构造时赋值一次。
* `name()` :返回代币的名称。
* `symbol()` :返回代币的符号,通常是名称的缩写。
* `decimals()` :返回小数点后位数,通常是 18 ,模仿 Ether 和 wei 。要更改就重写它。
`totalSupply()、balanceOf(address account)、transfer(address to, uint256 amount)、 allowance(address owner, address spender)、approve(address spender, uint256 amount)、transferFrom(address from, address to, uint256 amount)` 都参考 IERC20 。
* `increaseAllowance(address spender, uint256 addedValue)` :以原子的方式增加 **`spender`** 额度。返回布尔值告知是否执行成功,触发 **`Approval`** 事件。
* `_transfer(address from, address to, uint256 amount)` :转账。这个内部函数相当于 **`transfer`** ,可以用于例如实施自动代币费用,削减机制等。触发 **`Transfer`** 事件。
* `_mint(address account, uint256 amount)` :铸造 **`amount`** 数量的代币给 **`account`** 地址,增加总发行量。触发 **`Transfer`** 事件,其中参数 **`from`** 是零地址。
* `_burn(address account, uint256 amount)` :从 **`account`** 地址中烧毁 **`amount`** 数量的代币,减少总发行量。触发 **`Transfer`** 事件,其中参数 **`to`** 是零地址。
* `_approve(address owner, uint256 spender, uint256 amount)` :设定允许 **`spender`** 花费 **`owner`** 的代币数量。这个内部函数相当于 **`approve`** ,可以用于例如为某些子系统设置自动限额等。
* `spendAllowance(address owner, address spender, uint256 amount)` :花费 **`amount`** 数量的 **`owner`** 授权 **`spender`** 的代币。在无限 allowance 的情况下不更新 allowance 金额。如果没有足够的余量,则恢复。可能触发 **`Approval`** 事件。
* `_beforeTokenTransfer(address from, address to, uint256 amount)` :在任何代币转账前的 Hook 。它包括铸币和烧毁。调用条件:
* **当 **`from`** 和 **`to`** 都不是零地址时,**`from` 手里 **`amount`** 数量的代币将发送给 **`to`** 。
* **当 **`from`** 是零地址时,将给 **`to`** 铸造 **`amount`** 数量的代币。**
* **当 **`to`** 是零地址时,**`from` 手里 **`amount`** 数量的代币将被烧毁。
* `from` 和 **`to`** 不能同时为零地址。
* `_afterTokenTransfer(address from, address to, uint256 amount)` :在任何代币转账后的 Hook 。它包括铸币和烧毁。调用条件:
* **当 **`from`** 和 **`to`** 都不是零地址时,**`from` 手里 **`amount`** 数量的代币将发送给 **`to`** 。
* **当 **`from`** 是零地址时,将给 **`to`** 铸造 **`amount`** 数量的代币。**
* **当 **`to`** 是零地址时,**`from` 手里 **`amount`** 数量的代币将被烧毁。
* `from` 和 **`to`** 不能同时为零地址。
#### **小结**
**ERC20 代码中的 **`_transfer`**、**`_mint`**、**`_burn`**、**`_approve`**、**`_spendAllowance`**、**`_beforeTokenTransfer`**、**`_afterTokenTransfer` 都是 **`internal`** 函数(其余为 **`public`** ),也就是说它们只能被派生合约调用。
## **从零开始,自己动手**
### **1.编写IERC20**
[**IERC20.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/IERC20.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
/// @dev 总发行量
function totoalSupply() external view returns (uint256);
/// @dev 查看地址余额
function balanceOf(address account) external view returns (uint256);
/// @dev 单地址转账
function transfer(address account, uint256 amount) external returns (bool);
/// @dev 查看被授权人代表所有者花费的代币余额
function allowance(address owner, address spender) external view returns (uint256);
/// @dev 授权别人花费你拥有的代币
function approve(address spender, uint256 amount) external returns (bool);
/// @dev 双地址转账
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @dev 发生代币转移时触发
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev 授权时触发
event Approval(address indexed owner, address indexed spender, uint256 value);
}
```
### **2.加上Metadata**
[**IERC20Metadata.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/IERC20Metadata.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
/// @dev 代币名称
function name() external view returns (string memory);
/// @dev 代币符号
function symbol() external view returns (string memory);
/// @dev 小数点后位数
function decimals() external view returns (uint8);
}
```
### **3.编写ERC20**
[**ERC20.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/ERC20.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
contract ERC20 is IERC20, IERC30Metadata {
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/// @dev 设定代币名称符号
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/// @dev 小数点位数一般为 18
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 substractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= substractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approval(owner, spender, currentAllowance - substractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender];
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
```
## **总结**
**ERC20 其实就是一种最常见的代币标准,它明确了同质化代币的经典功能并规范了开发者编写 token 时的代码,从而方便各种应用适配。**
ERC20解读
参考 OpenZepplin文档 和 以太坊官方开发者文档,结合自己的理解。
博客的 Markdown 编辑器暂不支持 Solidity 语法高亮,为了更好阅读代码,可以去 我的GitHub仓库 。
什么是ERC20
ERC20(Ethereum Request for Comments 20)一种代币标准。EIP-20 中提出。
ERC20 代币合约跟踪同质化(可替代)代币:任何一个代币都完全等同于任何其他代币;没有任何代币具有与之相关的特殊权利或行为。这使得 ERC20 代币可用于交换货币、投票权、质押等媒介。
为什么要遵守ERC20
EIP-20 中的动机:
允许以太坊上的任何代币被其他应用程序(从钱包到去中心化交易所)重新使用的标准接口。
以太坊上的所有应用都默认支持 ERC20 ,如果你想自己发币,那么你的代码必须遵循 ERC20 标准,这样钱包(如MetaMask)等应用才能将你的币显示出来。
代码实现
需要实现以下函数和事件:
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
使用 OpenZeppllin 提供的库能够轻松快速地构建 ERC20 Token 。
快速构建
这是一个 GLD token 。
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
通常,我们定义代币的发行量和代币名称及符号。
IERC20
先来看下 ERC20 的接口(IERC20),这方便我们在开发中直接定义 ERC20 代币。
同样地,OpenZepplin 为我们提供了相应的库,方便开发者导入即用。
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
EIP 中定义的 ERC20 标准接口:
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
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);
}
逐一分析
函数:
totalSupply() :返回总共的代币数量。
balanceOf(address account) :返回 account 地址拥有的代币数量。
transfer(address to, uint256 amount) :将 amount 数量的代币发送给 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
allowance(address owner, address spender) :返回授权花费者 spender 通过 transferFrom 代表所有者花费的剩余代币数量。默认情况下为零。当 approve 和 transferFrom 被调用时,值将改变。
approve(address spender, uint256 amount) :授权 spender 可以花费 amount 数量的代币,返回布尔值告知是否执行成功。触发 Approval 事件。
transferFrom(address from, address to, uint256 amount) :将 amount 数量的代币从 from 地址发送到 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
事件(定义中的 indexed 便于查找过滤):
Transfer(address from, address to, uint256 value) :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
Approval(address owner, address spender, uint256 value) :当代币所有者授权别人使用代币时触发,即调用 approve 方法。
元数据
一般除了上述必须实现的函数外,还有一些别的方法:
name() :返回代币名称
symbol() :返回代币符号
decimals() :返回代币小数点后位数
ERC20
来看下 ERC20 代币具体是怎么写的。
同样,OpenZepplin 提供了现成的合约代码:
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
这里贴一个GitHub源码链接 OpenZepplin ERC20
函数概览
constructor(name_, symbol_)
name()
symbol()
decimals()
totalSupply()
balanceOf(account)
transfer(to, amount)
allowance(owner, spender)
approve(spender, amount)
transferFrom(from, to, amount)
increaseAllowance(spender, addedValue)
decreaseAllowance(spender, subtractedValue)
_transfer(from, to, amount)
_mint(account, amount)
_burn(account, amount)
_approve(owner, spender, amount)
_spendAllowance(owner, spender, amount)
_beforeTokenTransfer(from, to, amount)
_afterTokenTransfer(from, to, amount)
事件(同 IERC20)
Transfer(from, to, value)
Approval(owner, spender, value)
逐一分析
constructor(string name, string symbol) :设定代币的名称和符号。decimals 默认是 18 ,要修改成不同的值你应该重载它。这两个值是不变的,只在构造时赋值一次。
name() :返回代币的名称。
symbol() :返回代币的符号,通常是名称的缩写。
decimals() :返回小数点后位数,通常是 18 ,模仿 Ether 和 wei 。要更改就重写它。
totalSupply()、balanceOf(address account)、transfer(address to, uint256 amount)、 allowance(address owner, address spender)、approve(address spender, uint256 amount)、transferFrom(address from, address to, uint256 amount) 都参考 IERC20 。
increaseAllowance(address spender, uint256 addedValue) :以原子的方式增加 spender 额度。返回布尔值告知是否执行成功,触发 Approval 事件。
_transfer(address from, address to, uint256 amount) :转账。这个内部函数相当于 transfer ,可以用于例如实施自动代币费用,削减机制等。触发 Transfer 事件。
_mint(address account, uint256 amount) :铸造 amount 数量的代币给 account 地址,增加总发行量。触发 Transfer 事件,其中参数 from 是零地址。
_burn(address account, uint256 amount) :从 account 地址中烧毁 amount 数量的代币,减少总发行量。触发 Transfer 事件,其中参数 to 是零地址。
_approve(address owner, uint256 spender, uint256 amount) :设定允许 spender 花费 owner 的代币数量。这个内部函数相当于 approve ,可以用于例如为某些子系统设置自动限额等。
spendAllowance(address owner, address spender, uint256 amount) :花费 amount 数量的 owner 授权 spender 的代币。在无限 allowance 的情况下不更新 allowance 金额。如果没有足够的余量,则恢复。可能触发 Approval 事件。
_beforeTokenTransfer(address from, address to, uint256 amount) :在任何代币转账前的 Hook 。它包括铸币和烧毁。调用条件:
当 from 和 to 都不是零地址时,from 手里 amount 数量的代币将发送给 to 。
当 from 是零地址时,将给 to 铸造 amount 数量的代币。
当 to 是零地址时,from 手里 amount 数量的代币将被烧毁。
from 和 to 不能同时为零地址。
_afterTokenTransfer(address from, address to, uint256 amount) :在任何代币转账后的 Hook 。它包括铸币和烧毁。调用条件:
当 from 和 to 都不是零地址时,from 手里 amount 数量的代币将发送给 to 。
当 from 是零地址时,将给 to 铸造 amount 数量的代币。
当 to 是零地址时,from 手里 amount 数量的代币将被烧毁。
from 和 to 不能同时为零地址。
小结
ERC20 代码中的 _transfer、_mint、_burn、_approve、_spendAllowance、_beforeTokenTransfer、_afterTokenTransfer 都是 internal 函数(其余为 public ),也就是说它们只能被派生合约调用。
从零开始,自己动手
1.编写IERC20
IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
/// @dev 总发行量
function totoalSupply() external view returns (uint256);
/// @dev 查看地址余额
function balanceOf(address account) external view returns (uint256);
/// @dev 单地址转账
function transfer(address account, uint256 amount) external returns (bool);
/// @dev 查看被授权人代表所有者花费的代币余额
function allowance(address owner, address spender) external view returns (uint256);
/// @dev 授权别人花费你拥有的代币
function approve(address spender, uint256 amount) external returns (bool);
/// @dev 双地址转账
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @dev 发生代币转移时触发
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev 授权时触发
event Approval(address indexed owner, address indexed spender, uint256 value);
}
2.加上Metadata
IERC20Metadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
/// @dev 代币名称
function name() external view returns (string memory);
/// @dev 代币符号
function symbol() external view returns (string memory);
/// @dev 小数点后位数
function decimals() external view returns (uint8);
}
3.编写ERC20
ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
contract ERC20 is IERC20, IERC30Metadata {
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/// @dev 设定代币名称符号
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/// @dev 小数点位数一般为 18
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 substractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= substractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approval(owner, spender, currentAllowance - substractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender];
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
总结
ERC20 其实就是一种最常见的代币标准,它明确了同质化代币的经典功能并规范了开发者编写 token 时的代码,从而方便各种应用适配。
学分: 39
分类: 以太坊
标签:
ERC20
点赞 3
收藏 5
分享
Twitter分享
微信扫码分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
你可能感兴趣的文章
花式发币法之发行各类 ERC20 代币
3968 浏览
Michael.W基于Foundry精读Openzeppelin第39期——ERC20.sol
506 浏览
教程:如何在没有 Web 界面的情况下创建 ERC20桥
1574 浏览
一个简单的ERC20代币空投合约
2653 浏览
发布一款ERC20代币,并开发成Dapp
1548 浏览
Aptos合约开发之部署ERC20合约
3944 浏览
相关问题
请教下大家,Swap如何实现卖币手续费
2 回答
如何从发起部署的地址中,转移一部分代币到已经部署的合约地址中,麻烦那位大佬看一下
5 回答
空投的默克尔树如何防止生日攻击?
2 回答
bsc链上的erc20合约,要求只有一点买卖的时候2%兑换成bnb发送到营销钱包,现在的问题是添加流动性会一直报错Fail with error 'TransferHelper::transferFrom: transferFrom failed'
2 回答
eth中如何判断合约是erc20合约
2 回答
寻找使用Vyper部署的带有交易税的ERC20代币模版
1 回答
0 条评论
请先 登录 后评论
Confucian
关注
贡献值: 57
学分: 83
Keep Learning
文章目录
关于
关于我们
社区公约
学分规则
Github
伙伴们
DeCert
ChainTool
GCC
合作
广告投放
发布课程
联系我们
友情链接
关注社区
Discord
Youtube
B 站
公众号
关注不错过动态
微信群
加入技术圈子
©2024 登链社区 版权所有 |
Powered By Tipask3.5|
粤公网安备 44049102496617号
粤ICP备17140514号
粤B2-20230927
增值电信业务经营许可证
×
发送私信
请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!
发给:
内容:
取消
发送
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
取消
举报
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
ERC-20 代币标准 | ethereum.org
20 代币标准 | ethereum.org跳转至主要内容学习用法构建参与研究搜索语言 ZH帮助更新此页面本页面有新版本,但现在只有英文版。请帮助我们翻译最新版本。翻译页面没有错误!此页面未翻译,因此特意以英文显示。不再显示Change page概述基础主题以太坊简介以太币简介去中心化应用程序简介Web2 与 Web3 的对比帐户交易区块以太坊虚拟机 (EVM)操作码Gas费用节点和客户端运行节点客户端多样性节点即服务节点架构轻客户端归档节点引导节点网络共识机制工作量证明矿工挖矿算法Dagger-HashimotoEthash权益证明Gasper弱主观性认证权益证明机制的奖励和惩罚权益证明攻击与防御密钥权益证明与工作量证明提出区块权益正明常见问题以太坊堆栈堆栈简介智能合约智能合约语言智能合约结构智能合约库测试用智能合约编译智能合约部署智能合约验证智能合约升级智能合约智能合约安全性智能合约形式化验证可组合性开发网络开发框架以太坊客户端APIJavaScript API后端APIJSON-RPC数据和分析区块浏览器存储集成开发环境 (IDE)编程语言DartDelphi.NETGolangJavaJavaScriptPythonRubyRust语言高级链桥标准令牌标准ERC-20:同质化代币ERC-721:非同质化代币 (NFT)ERC-777ERC-1155ERC-4626最大可提取价值 (MEV)预言机缩放乐观卷叠零知识卷叠状态通道侧链以太坊 Plasma 扩容解决方案Validium数据可用性网络层网络地址门户网络数据结构与编码默克尔前缀树递归长度前缀编码 (RLP)简单序列化 (SSZ)Web3 密钥存储定义设计基础设计和用户体验简介ERC-20 代币标准p上次修改时间: @penglaishan.cn(opens in a new tab), Invalid DateTime查看贡献者在本页面介绍前提条件正文方法事件示例延伸阅读介绍什么叫做代币?代币可以在以太坊中表示任何东西:在线平台中的信誉积分游戏中一个角色的技能彩票卷金融资产类似于公司股份的资产像美元一样的法定货币一盎司黄金及更多...以太坊的这种强大特点必须以强有力的标准来处理,对吗? 这正是 ERC-20 发挥其作用的地方! 此标准允许开发者构建可与其他产品和服务互相操作的代币应用程序。什么是 ERC-20?ERC-20 提出了一个同质化代币的标准,换句话说,它们具有一种属性,使得每个代币都与另一个代币(在类型和价值上)完全相同。 例如,一个 ERC-20 代币就像以太币一样,意味着一个代币会并永远会与其他代币一样。前提条件帐户智能合约代币标准正文ERC-20(以太坊意见征求 20)由 Fabian Vogelsteller 提出于 2015 年 11 月。这是一个能实现智能合约中代币的应用程序接口标准。ERC-20 的功能示例包括:将代币从一个帐户转到另一个帐户获取帐户的当前代币余额获取网络上可用代币的总供应量批准一个帐户中一定的代币金额由第三方帐户使用如果智能合约实施了下列方法和事件,它可以被称为 ERC-20 代币合约,一旦部署,将负责跟踪以太坊上创建的代币。来自 EIP-20(opens in a new tab):方法1function name() public view returns (string)2function symbol() public view returns (string)3function decimals() public view returns (uint8)4function totalSupply() public view returns (uint256)5function balanceOf(address _owner) public view returns (uint256 balance)6function transfer(address _to, uint256 _value) public returns (bool success)7function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)8function approve(address _spender, uint256 _value) public returns (bool success)9function allowance(address _owner, address _spender) public view returns (uint256 remaining)显示全部 复制事件1event Transfer(address indexed _from, address indexed _to, uint256 _value)2event Approval(address indexed _owner, address indexed _spender, uint256 _value) 复制示例让我们看看如此重要的一个标准是如何使我们能够简单地检查以太坊上的任何 ERC-20 代币合约。 我们只需要合约的应用程序二进制接口 (ABI) 来创造一个 ERC-20 代币界面。 下面我们将使用一个简化的应用程序二进制接口,让例子变得更为简单。Web3.py 示例首先,请确保您已安装 Web3.py(opens in a new tab) Python 库:1pip install web31from web3 import Web3234w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))56dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI7weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH)89acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 21011# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract.12# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply()13simplified_abi = [14 {15 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}],16 'name': 'balanceOf',17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],18 'stateMutability': 'view', 'type': 'function', 'constant': True19 },20 {21 'inputs': [],22 'name': 'decimals',23 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}],24 'stateMutability': 'view', 'type': 'function', 'constant': True25 },26 {27 'inputs': [],28 'name': 'symbol',29 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],30 'stateMutability': 'view', 'type': 'function', 'constant': True31 },32 {33 'inputs': [],34 'name': 'totalSupply',35 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],36 'stateMutability': 'view', 'type': 'function', 'constant': True37 }38]3940dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi)41symbol = dai_contract.functions.symbol().call()42decimals = dai_contract.functions.decimals().call()43totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals44addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals4546# DAI47print("===== %s =====" % symbol)48print("Total Supply:", totalSupply)49print("Addr Balance:", addr_balance)5051weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi)52symbol = weth_contract.functions.symbol().call()53decimals = weth_contract.functions.decimals().call()54totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals55addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals5657# WETH58print("===== %s =====" % symbol)59print("Total Supply:", totalSupply)60print("Addr Balance:", addr_balance)显示全部 复制延伸阅读EIP-20:ERC-20 代币标准(opens in a new tab)OpenZeppelin - 代币(opens in a new tab)OpenZeppelin - ERC-20 实施(opens in a new tab)back-to-top ↑本文对你有帮助吗?是否前一页令牌标准下一页ERC-721:非同质化代币 (NFT)编辑页面(opens in a new tab)在本页面介绍前提条件正文方法事件示例延伸阅读网站最后更新: 2024年3月13日(opens in a new tab)(opens in a new tab)(opens in a new tab)学习学习中心什么是以太坊?什么是以太币 (ETH)?以太坊钱包什么是 Web3?智能合约Gas fees运行节点以太坊安全和预防欺诈措施测试中心以太坊词汇表用法指南选择钱包获取以太币Dapps - 去中心化应用稳定币NFT - 非同质化代币DeFi - 去中心化金融DAO - 去中心化自治组织去中心化身份质押ETH二层网络构建构建者首页教程相关文档通过编码来学习设置本地环境资助基础主题用户体验/用户界面设计基础Enterprise - Mainnet EthereumEnterprise - Private Ethereum参与社区中心在线社区以太坊活动为 ethereum.org 做贡献翻译计划以太坊漏洞悬赏计划以太坊基金会以太坊基金会的博客(opens in a new tab)生态系统支持方案(opens in a new tab)Devcon(opens in a new tab)研究以太坊白皮书以太坊路线图安全性增强以太坊技术史开放研究以太坊改进提案 (Eip)以太坊治理关于我们以太坊品牌资产Code of conduct工作机会隐私政策使用条款缓存政策联系我们(opens in a new tab)本页面对你有帮什么是ERC-20? - 知乎
什么是ERC-20? - 知乎切换模式写文章登录/注册什么是ERC-20?穆逸扬Myytydy用注意力写作,用比特币存钱摘要简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币;我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献,也是以太坊网络第一个真正意义上的杀手级应用。以下是正文这次的更新我们来聊聊ERC-20这个你很可能听过,但大概率一知半解的区块链“黑话”。如果你是定投人生课堂的成员,或者正在践行定投区块链数字资产的策略,相信ERC-20这个词对你而言一定不陌生。ERC-20的定义如同CoinDesk专栏作者 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中所说的:ERC-20以太坊代币标准是创建与更广泛的以太坊网络兼容的可替换代币的蓝图。以太坊,或称Ethereum,是一种加密货币,允许创建各种应用,包括代币,与大多数传统应用不同,它不需要中心化服务机构就可以运作。上面引述的内容可能不太好理解,简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。其中的ERC是"EthereumRequest for Comment"也就是“以太坊征求意见协议”的缩写。和其他的开源社区一样,以太坊会使用这样的方式收集开发者的反馈、并在批准后作为后续开发的执行标准。ERC-20的价值和影响毫无疑问,ERC-20是所有ERC协议中最广为人知的一个。我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献(此处完全可以去掉“之一”,我甚至不介意再去掉“早期”)。是的,在我看来ERC-20就是以太坊网络第一个真正意义上的杀手级应用。正是因为有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币。也正是这一协议提供的这种极大的便利,使得首次代币发行,也就是大名鼎鼎同时饱受争议的ICO,能一度在区块链世界大行其道——助长大量骗局的同时,也在客观上推动了区块链相关技术与应用的爆发式增长。更有趣的是,ERC-20的火爆甚至直接催生了一些类似TRC-20这样,连协议的数字代号都懒得改一下的像素级山寨竞品。一个便于理解的类比如果上面的这些叙述还是让你一知半解,甚至完全摸不到头脑,我们不妨打个容易理解的比方:如果我们把众多区块链项目的开发者,看作是在一个小区门口商铺里,经营不同业态的众多商户。这些商户根据自己的专长提供各自不同的商品和服务,也都希望发行自己店铺专属的消费储值卡。方便消费者光顾的同时,也能提升用户的体验和粘性。以太坊就像是运营这个小区底商的物业公司,它提供一整套标准化的储值卡发放协议和配套服务。借助这套叫做ERC-20的整体解决方案,每个商户(开发者)都可以傻瓜式地发行专属于自己店铺的消费储值卡,同时由于这种储值卡采用了统一的协议,可以非常方便地和其他商户的储值卡做无缝兑换。于是借助ERC-20,用户可以通过持有其中一种储值卡(token)很方便地享受整个生态的各种服务;商户(开发者)则节约了开发运营成本、同时提升了获取用户的效率;而物业公司(以太坊基金会和矿工)则可以通过做大生态体量实现更多的租金(ETH增值)和储值卡结算手续费(Gas费用)收入。ERC-20就是用这种做大生态价值的方式,实现了用户、开发者和以太坊网络三方面的共赢。ERC-20的应用案例为了让你对ERC-20有更具象化的认识,这里援引 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中列举的一些比较知名的基于ERC-20协议代币:Tether (USDT)Chainlink (LINK)Binance coin (BNB)USD coin (USDC)Wrapped bitcoin (WBTC)Dai (DAI)需要特别指出的是,这上面提到的Tether发行的稳定币USDT除了基于ERC-20协议的版本之外,其实还有基于其他公链发行的多个版本,只不过ERC-20版的发行量最大,知名度也最高。ERC-20与BOX的关系ERC-20版本的USDT,在我们定投人生课堂的战友定投BOX的过程中,也有很广泛的应用。比如通过ExinOne(Mixin ID:7000101276),可以轻松实现存USDT自动执行每周/每日定投BOX的操作。说到BOX这个区块链数字资产开源配方,它和ERC-20的关系也十分密切——其中的两个成分,XIN、UNI就是基于ERC-20协议发行的代币,此外BOX本身同样是一个基于此协议发行的Token——可以说,如果没有ERC-20,BOX这个区块链数字资产开源配方就不会是现在这个样子了。参考内容What is the ERC-20 Ethereum Token Standard?ERC 协议终极解读:ERC-20你常听到的 ERC20 和 ERC721 到底是什么?一文弄懂什么是 ERC20BOX简介发布于 2021-12-02 16:01虚拟货币区块链(Blockchain)ethereum赞同 5添加评论分享喜欢收藏申请
ERC-20 代币标准 | ethereum.org
20 代币标准 | ethereum.org跳转至主要内容学习用法构建参与研究搜索语言 ZH帮助更新此页面本页面有新版本,但现在只有英文版。请帮助我们翻译最新版本。翻译页面没有错误!此页面未翻译,因此特意以英文显示。不再显示Change page概述基础主题以太坊简介以太币简介去中心化应用程序简介Web2 与 Web3 的对比帐户交易区块以太坊虚拟机 (EVM)操作码Gas费用节点和客户端运行节点客户端多样性节点即服务节点架构轻客户端归档节点引导节点网络共识机制工作量证明矿工挖矿算法Dagger-HashimotoEthash权益证明Gasper弱主观性认证权益证明机制的奖励和惩罚权益证明攻击与防御密钥权益证明与工作量证明提出区块权益正明常见问题以太坊堆栈堆栈简介智能合约智能合约语言智能合约结构智能合约库测试用智能合约编译智能合约部署智能合约验证智能合约升级智能合约智能合约安全性智能合约形式化验证可组合性开发网络开发框架以太坊客户端APIJavaScript API后端APIJSON-RPC数据和分析区块浏览器存储集成开发环境 (IDE)编程语言DartDelphi.NETGolangJavaJavaScriptPythonRubyRust语言高级链桥标准令牌标准ERC-20:同质化代币ERC-721:非同质化代币 (NFT)ERC-777ERC-1155ERC-4626最大可提取价值 (MEV)预言机缩放乐观卷叠零知识卷叠状态通道侧链以太坊 Plasma 扩容解决方案Validium数据可用性网络层网络地址门户网络数据结构与编码默克尔前缀树递归长度前缀编码 (RLP)简单序列化 (SSZ)Web3 密钥存储定义设计基础设计和用户体验简介ERC-20 代币标准p上次修改时间: @penglaishan.cn(opens in a new tab), Invalid DateTime查看贡献者在本页面介绍前提条件正文方法事件示例延伸阅读介绍什么叫做代币?代币可以在以太坊中表示任何东西:在线平台中的信誉积分游戏中一个角色的技能彩票卷金融资产类似于公司股份的资产像美元一样的法定货币一盎司黄金及更多...以太坊的这种强大特点必须以强有力的标准来处理,对吗? 这正是 ERC-20 发挥其作用的地方! 此标准允许开发者构建可与其他产品和服务互相操作的代币应用程序。什么是 ERC-20?ERC-20 提出了一个同质化代币的标准,换句话说,它们具有一种属性,使得每个代币都与另一个代币(在类型和价值上)完全相同。 例如,一个 ERC-20 代币就像以太币一样,意味着一个代币会并永远会与其他代币一样。前提条件帐户智能合约代币标准正文ERC-20(以太坊意见征求 20)由 Fabian Vogelsteller 提出于 2015 年 11 月。这是一个能实现智能合约中代币的应用程序接口标准。ERC-20 的功能示例包括:将代币从一个帐户转到另一个帐户获取帐户的当前代币余额获取网络上可用代币的总供应量批准一个帐户中一定的代币金额由第三方帐户使用如果智能合约实施了下列方法和事件,它可以被称为 ERC-20 代币合约,一旦部署,将负责跟踪以太坊上创建的代币。来自 EIP-20(opens in a new tab):方法1function name() public view returns (string)2function symbol() public view returns (string)3function decimals() public view returns (uint8)4function totalSupply() public view returns (uint256)5function balanceOf(address _owner) public view returns (uint256 balance)6function transfer(address _to, uint256 _value) public returns (bool success)7function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)8function approve(address _spender, uint256 _value) public returns (bool success)9function allowance(address _owner, address _spender) public view returns (uint256 remaining)显示全部 复制事件1event Transfer(address indexed _from, address indexed _to, uint256 _value)2event Approval(address indexed _owner, address indexed _spender, uint256 _value) 复制示例让我们看看如此重要的一个标准是如何使我们能够简单地检查以太坊上的任何 ERC-20 代币合约。 我们只需要合约的应用程序二进制接口 (ABI) 来创造一个 ERC-20 代币界面。 下面我们将使用一个简化的应用程序二进制接口,让例子变得更为简单。Web3.py 示例首先,请确保您已安装 Web3.py(opens in a new tab) Python 库:1pip install web31from web3 import Web3234w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))56dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI7weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH)89acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 21011# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract.12# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply()13simplified_abi = [14 {15 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}],16 'name': 'balanceOf',17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],18 'stateMutability': 'view', 'type': 'function', 'constant': True19 },20 {21 'inputs': [],22 'name': 'decimals',23 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}],24 'stateMutability': 'view', 'type': 'function', 'constant': True25 },26 {27 'inputs': [],28 'name': 'symbol',29 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],30 'stateMutability': 'view', 'type': 'function', 'constant': True31 },32 {33 'inputs': [],34 'name': 'totalSupply',35 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],36 'stateMutability': 'view', 'type': 'function', 'constant': True37 }38]3940dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi)41symbol = dai_contract.functions.symbol().call()42decimals = dai_contract.functions.decimals().call()43totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals44addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals4546# DAI47print("===== %s =====" % symbol)48print("Total Supply:", totalSupply)49print("Addr Balance:", addr_balance)5051weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi)52symbol = weth_contract.functions.symbol().call()53decimals = weth_contract.functions.decimals().call()54totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals55addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals5657# WETH58print("===== %s =====" % symbol)59print("Total Supply:", totalSupply)60print("Addr Balance:", addr_balance)显示全部 复制延伸阅读EIP-20:ERC-20 代币标准(opens in a new tab)OpenZeppelin - 代币(opens in a new tab)OpenZeppelin - ERC-20 实施(opens in a new tab)back-to-top ↑本文对你有帮助吗?是否前一页令牌标准下一页ERC-721:非同质化代币 (NFT)编辑页面(opens in a new tab)在本页面介绍前提条件正文方法事件示例延伸阅读网站最后更新: 2024年3月13日(opens in a new tab)(opens in a new tab)(opens in a new tab)学习学习中心什么是以太坊?什么是以太币 (ETH)?以太坊钱包什么是 Web3?智能合约Gas fees运行节点以太坊安全和预防欺诈措施测试中心以太坊词汇表用法指南选择钱包获取以太币Dapps - 去中心化应用稳定币NFT - 非同质化代币DeFi - 去中心化金融DAO - 去中心化自治组织去中心化身份质押ETH二层网络构建构建者首页教程相关文档通过编码来学习设置本地环境资助基础主题用户体验/用户界面设计基础Enterprise - Mainnet EthereumEnterprise - Private Ethereum参与社区中心在线社区以太坊活动为 ethereum.org 做贡献翻译计划以太坊漏洞悬赏计划以太坊基金会以太坊基金会的博客(opens in a new tab)生态系统支持方案(opens in a new tab)Devcon(opens in a new tab)研究以太坊白皮书以太坊路线图安全性增强以太坊技术史开放研究以太坊改进提案 (Eip)以太坊治理关于我们以太坊品牌资产Code of conduct工作机会隐私政策使用条款缓存政策联系我们(opens in a new tab)本页面对你有帮什么是ERC-20? - 知乎
什么是ERC-20? - 知乎切换模式写文章登录/注册什么是ERC-20?穆逸扬Myytydy用注意力写作,用比特币存钱摘要简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币;我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献,也是以太坊网络第一个真正意义上的杀手级应用。以下是正文这次的更新我们来聊聊ERC-20这个你很可能听过,但大概率一知半解的区块链“黑话”。如果你是定投人生课堂的成员,或者正在践行定投区块链数字资产的策略,相信ERC-20这个词对你而言一定不陌生。ERC-20的定义如同CoinDesk专栏作者 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中所说的:ERC-20以太坊代币标准是创建与更广泛的以太坊网络兼容的可替换代币的蓝图。以太坊,或称Ethereum,是一种加密货币,允许创建各种应用,包括代币,与大多数传统应用不同,它不需要中心化服务机构就可以运作。上面引述的内容可能不太好理解,简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。其中的ERC是"EthereumRequest for Comment"也就是“以太坊征求意见协议”的缩写。和其他的开源社区一样,以太坊会使用这样的方式收集开发者的反馈、并在批准后作为后续开发的执行标准。ERC-20的价值和影响毫无疑问,ERC-20是所有ERC协议中最广为人知的一个。我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献(此处完全可以去掉“之一”,我甚至不介意再去掉“早期”)。是的,在我看来ERC-20就是以太坊网络第一个真正意义上的杀手级应用。正是因为有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币。也正是这一协议提供的这种极大的便利,使得首次代币发行,也就是大名鼎鼎同时饱受争议的ICO,能一度在区块链世界大行其道——助长大量骗局的同时,也在客观上推动了区块链相关技术与应用的爆发式增长。更有趣的是,ERC-20的火爆甚至直接催生了一些类似TRC-20这样,连协议的数字代号都懒得改一下的像素级山寨竞品。一个便于理解的类比如果上面的这些叙述还是让你一知半解,甚至完全摸不到头脑,我们不妨打个容易理解的比方:如果我们把众多区块链项目的开发者,看作是在一个小区门口商铺里,经营不同业态的众多商户。这些商户根据自己的专长提供各自不同的商品和服务,也都希望发行自己店铺专属的消费储值卡。方便消费者光顾的同时,也能提升用户的体验和粘性。以太坊就像是运营这个小区底商的物业公司,它提供一整套标准化的储值卡发放协议和配套服务。借助这套叫做ERC-20的整体解决方案,每个商户(开发者)都可以傻瓜式地发行专属于自己店铺的消费储值卡,同时由于这种储值卡采用了统一的协议,可以非常方便地和其他商户的储值卡做无缝兑换。于是借助ERC-20,用户可以通过持有其中一种储值卡(token)很方便地享受整个生态的各种服务;商户(开发者)则节约了开发运营成本、同时提升了获取用户的效率;而物业公司(以太坊基金会和矿工)则可以通过做大生态体量实现更多的租金(ETH增值)和储值卡结算手续费(Gas费用)收入。ERC-20就是用这种做大生态价值的方式,实现了用户、开发者和以太坊网络三方面的共赢。ERC-20的应用案例为了让你对ERC-20有更具象化的认识,这里援引 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中列举的一些比较知名的基于ERC-20协议代币:Tether (USDT)Chainlink (LINK)Binance coin (BNB)USD coin (USDC)Wrapped bitcoin (WBTC)Dai (DAI)需要特别指出的是,这上面提到的Tether发行的稳定币USDT除了基于ERC-20协议的版本之外,其实还有基于其他公链发行的多个版本,只不过ERC-20版的发行量最大,知名度也最高。ERC-20与BOX的关系ERC-20版本的USDT,在我们定投人生课堂的战友定投BOX的过程中,也有很广泛的应用。比如通过ExinOne(Mixin ID:7000101276),可以轻松实现存USDT自动执行每周/每日定投BOX的操作。说到BOX这个区块链数字资产开源配方,它和ERC-20的关系也十分密切——其中的两个成分,XIN、UNI就是基于ERC-20协议发行的代币,此外BOX本身同样是一个基于此协议发行的Token——可以说,如果没有ERC-20,BOX这个区块链数字资产开源配方就不会是现在这个样子了。参考内容What is the ERC-20 Ethereum Token Standard?ERC 协议终极解读:ERC-20你常听到的 ERC20 和 ERC721 到底是什么?一文弄懂什么是 ERC20BOX简介发布于 2021-12-02 16:01虚拟货币区块链(Blockchain)ethereum赞同 5添加评论分享喜欢收藏申请
Buy/Sell Bitcoin, Ether and Altcoins | Cryptocurrency Exchange | Binance
Buy/Sell Bitcoin, Ether and Altcoins | Cryptocurrency Exchange | Binance
Error 403 Forbidden - This request is blocked.
For security reasons you can't connect to the server for this app or website at this time.
It maybe that you have too many requests or the illegal request payload is identified as an attack.
Please try again later.
[block #32] 详解ERC20与ERC721 - 知乎
[block #32] 详解ERC20与ERC721 - 知乎首发于勤学苦链切换模式写文章登录/注册[block #32] 详解ERC20与ERC721猫本聪摘要数字加密货币大致可以分为原生币(coin)和代币(token)两大类。前者如BTC、ETH等,拥有自己的区块链。后者如Tether、TRON、ONT等,依附于现有的区块链。市场上流通的基于以太坊的代币大都遵从ERC20协议。最近几个月间还出现了一种被称为ERC721的数字加密资产,例如CryptoKitties(参阅[block #24])。所谓ERC20和ERC721究竟是什么呢?首先,ERC是Ethereum Request for Comments的缩写,代表以太坊开发者提交的协议提案。它相当于是以太坊版的RFC(https://www.ietf.org/standards/rfcs/)。ERC后面的数字是议案的编号。打算制定以太坊新标准的开发者可以在https://github.com/ethereum/EIPs/issues先创建一个EIP(Ethereum Improvement Proposal,以太坊改进提案),详细描述协议。经过公开审议之后,获得广泛认同的提案会被标准化,列入https://github.com/ethereum/EIPs。有些改动触及区块链共识,比如增加虚拟机操作符,属于核心层变更。而另一些提案则不涉及修改以太坊本身的代码,只是约定俗成的上层协议,它们通常被归类为ERC标准。ERC20可能是其中最广为人知的标准了。它诞生于2015年,到2017年9月被正式标准化。协议规定了具有可互换性(fungible)代币的一组基本接口,包括代币符号、发行量、转账、授权等。所谓可互换性(fungibility)指代币之间无差异,同等数量的两笔代币价值相等。交易所里流通的绝大部分代币都是可互换的,一单位的币无论在哪儿都价值一单位。与之相对的则是非互换性(non-fungible)资产。比如CryptoKitties中的宠物猫就是典型的非互换性资产,因为每只猫各有千秋,而且由于不同辈分的稀缺性不同,市场价格也差异巨大。这种非标准化资产很长时间内都没有标准协议,直到2017年9月才出现ERC721提案,定义了一组常用的接口。ERC721至今仍旧处于草案阶段,但已经被不少dApp采用,甚至出现了专门的交易所(Y Combinator孵化的http://opensea.io)。以下详细拆解ERC20和ERC721协议,技术性偏强,目标读者是以太坊智能合约开发者。ERC20ERC20定义了三个可选函数:// 代币名称。比如"Sleepism Token"。
function name() view returns (string name);
// 代币符号。按惯例一般用全大写字母,比如“SLPT”。
function symbol() view returns (string symbol);
// 小数位数。不少代币采用与ETH一样的设定,也就是18位。
// 这只影响用户界面中货币量的显示方式。代币本身都统一用uint256表示。
function decimal() view returns (uint8 decimals);由于这三个函数都是返回常量,在Solidity中也可以用以下简略形式定义。solc编译器会自动生成与以上接口等价的字节码。string public name = "Sleepism Token";
string public symbol = "SLPT";
uint8 public decimal = 18;ERC20定义了六个必须声明的函数:// 代币总量。
function totalSupply() view returns (uint256 totalSupply);
// 查询指定地址下的代币余额。
function balanceOf(address _owner) view returns (uint256 balance);
// 给指定地址转入指定量的代币,转账成功则返回true。
// 如果源地址没有足够量的代币,函数应该抛出异常。
// 即使转零个代币,也应该触发Transfer事件(下文中有解释)。
function transfer(address _to, uint256 _value) returns (bool success);
// 与transfer类似的转账函数。区别在于可以指定一个转出地址。
// 如果当前地址得到了转出地址的授权,则可以代理转账操作。
function transferFrom(address _from, address _to, uint256 _value)
returns (bool success);
// 授权指定地址特定的转账额度。
// 被授权的地址可以多次调用transferFrom函数代替源地址转账,总值不超过_value。
// 实际使用时,每次重设额度前应该先调用approve(_spender, 0),
// 等交易被确认后再调用approve(_spender, newAllowance)。
// 如果直接调用一次approve,被授权地址有机会转出高出指定额度的代币。
function approve(address _spender, uint256 _value) returns (bool success);
// 查询指定授权地址剩余的转账额度。
function allowance(address _owner, address _spender) view returns (uint256 remaining);ERC20还定义了两个事件:// 转账事件。必须在成功转账(哪怕是零个代币)时触发。
event Transfer(address indexed _from, address indexed _to, uint256 _value);
// 授权事件。必须在成功授权时触发。
event Approval(address indexed _owner, address indexed _spender, uint256 _value);官方文档参见https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md。ERC721ERC721与ERC20有些相似,但由于它管理的是非互换性资产(non-fungible token,简称NFT),所以函数语义并不一样。合约下每份ERC721资产都拥有一个uint256类型的独立编号(以下代码中的_tokenId)。ERC721事件:// 转账事件。从_from地址转移_tokenId对应资产的所有权到_to地址时触发。
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
// 授权转账事件。把_owner地址控制的_tokenId资产授权给_approved地址时触发。
// 发生转账事件时,对应资产的授权地址应被清空。
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
// 授权管理事件。_owner地址授权或取消授权_operator地址的管理权时触发。
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);ERC721函数:// 查询_owner地址拥有的NFT总个数。
function balanceOf(address _owner) external view returns (uint256);
// 查询_tokenId资产的所属地址。
function ownerOf(uint256 _tokenId) external view returns (address);
// 将_from地址所拥有的_tokenId资产转移给_to地址。
// 调用方必须是资产主人或是已被授权的地址,否则会抛出异常。
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
// 与transferFrom类似的资产转移函数。
// 它会额外检查_to地址和_tokenId的有效性,另外如果_to是合约地址,
// 还会触发它的onERC721Received回调函数。
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
// 与上述接口类似的资产转移函数。
// 唯一不同点是可以传入额外的自定义参数。
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
// 把_tokenId资产授权给_approved地址。
function approve(address _approved, uint256 _tokenId) external payable;
// 查询_tokenId资产对应的授权地址。
function getApproved(uint256 _tokenId) external view returns (address);
// 指定或撤销_operator地址的管理权限。
function setApprovalForAll(address _operator, bool _approved) external;
// 查询_operator地址是否已经获得_owner地址的管理权。
function isApprovedForAll(address _owner, address _operator) external view returns (bool);ERC721元数据接口(可选项):// 资产名称。比如"Sleepism Collectible"。
function name() external pure returns (string _name);
// 资产符号。比如"SLPC"。
function symbol() external pure returns (string _symbol);
// 描述_tokenId资产的URI。指向一个符合ERC721元数据描述结构的JSON文件。
function tokenURI(uint256 _tokenId) external view returns (string);元数据描述结构如下所示:{
"title": "Sleepism Collectible Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Sleep and his Half-brother Death",
},
"description": {
"type": "string",
"description": "A painting by John William Waterhouse",
},
"image": {
"type": "string",
"description": "https://i.imgur.com/sahhbd.png",
}
}
}ERC721枚举扩宽接口(可选项):// 合约管理的总NFT数量。
function totalSupply() external view returns (uint256);
// 查询第_index个资产的编码。
function tokenByIndex(uint256 _index) external view returns (uint256);
// 查询_owner地址拥有的第_index个资产的编码。
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);符合ERC721协议的合约还需要符合ERC165规范,实现以下函数:// 查询合约是否实现了interfaceID对应的接口。
function supportsInterface(bytes4 interfaceID) external view returns (bool);interfaceID由bytes4(keccak256(函数签名))计算得到。有多个函数时,将全部byte4异或(xor)得到最终结果。详见ERC165标准文档(https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md)。例如以下接受转账回调函数接口的interfaceID就是0xf0b9e5ba:interface ERC721TokenReceiver {
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
}这是支持ERC721资产的钱包或交易平台需要实现的代码。发放ERC721资产的合约本身不需要处理。ERC721官方文档参见https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md。相关ERCERC223是对ERC20的小改进,增加了tokenFallback函数,更好地处理错误情况。详见https://github.com/ethereum/EIPs/issues/223。ERC621在ERC20的基础上添加了increaseSupply和decreaseSupply函数,控制代币总量的增减。详见https://github.com/ethereum/EIPs/pull/621。更近期提出的ERC827则是增强了函数回调功能。详见https://github.com/ethereum/EIPs/issues/827。以上这些ERC尚未标准化,普及率也不高。目前参考一下即可。编辑于 2018-03-28 18:17区块链(Blockchain)智能合约赞同 468 条评论分享喜欢收藏申请转载文章被以下专栏收录勤学苦链加密货币相关(新内容见公众号maobenco
ERC20解读 | 登链社区 | 区块链技术社区
ERC20解读 | 登链社区 | 区块链技术社区
文章
问答
讲堂
专栏
集市
更多
提问
发表文章
活动
文档
招聘
发现
Toggle navigation
首页 (current)
文章
问答
讲堂
专栏
活动
招聘
文档
集市
搜索
登录/注册
ERC20解读
Confucian
更新于 2022-04-04 19:54
阅读 6965
对ERC20代币标准的个人解读
# ERC20解读
**参考 **[**OpenZepplin文档**](https://docs.openzeppelin.com/contracts/4.x/erc20)** 和 **[**以太坊官方开发者文档**](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)**,结合自己的理解。**
博客的 Markdown 编辑器暂不支持 Solidity 语法高亮,为了更好阅读代码,可以去 [**我的GitHub仓库**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/tree/main/ERC20) 。
## **什么是ERC20**
**ERC20(Ethereum Request for Comments 20)一种代币标准。**[**EIP-20**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 中提出。
**ERC20 代币合约跟踪同质化(可替代)代币:任何一个代币都完全等同于任何其他代币;没有任何代币具有与之相关的特殊权利或行为。这使得 ERC20 代币可用于交换货币、投票权、质押等媒介。**
## **为什么要遵守ERC20**
**EIP-20 中的动机:**
> **允许以太坊上的任何代币被其他应用程序(从钱包到去中心化交易所)重新使用的标准接口。**
**以太坊上的所有应用都默认支持 ERC20 ,如果你想自己发币,那么你的代码必须遵循 ERC20 标准,这样钱包(如MetaMask)等应用才能将你的币显示出来。**
## **代码实现**
**需要实现以下函数和事件:**
```
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
```
**使用 OpenZeppllin 提供的库能够轻松快速地构建 ERC20 Token 。**
### **快速构建**
**这是一个 GLD token 。**
```
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
```
**通常,我们定义代币的发行量和代币名称及符号。**
### **IERC20**
**先来看下 ERC20 的接口(IERC20),这方便我们在开发中直接定义 ERC20 代币。**
**同样地,OpenZepplin 为我们提供了相应的库,方便开发者导入即用。**
```
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
```
****EIP 中定义的 ERC20 标准接口:****
```
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
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);
}
```
#### **逐一分析**
**函数:**
* `totalSupply()` :返回总共的代币数量。
* `balanceOf(address account)` :返回 `account` 地址拥有的代币数量。
* `transfer(address to, uint256 amount)` :将 **`amount`** 数量的代币发送给 **`to`** 地址,返回布尔值告知是否执行成功。触发 **`Transfer`** 事件。
* `allowance(address owner, address spender)` :返回授权花费者 **`spender`** 通过 **`transferFrom`** 代表所有者花费的剩余代币数量。默认情况下为零。当 **`approve`** 和 **`transferFrom`** 被调用时,值将改变。
* `approve(address spender, uint256 amount)` :授权 **`spender`** 可以花费 **`amount`** 数量的代币,返回布尔值告知是否执行成功。触发 **`Approval`** 事件。
* `transferFrom(address from, address to, uint256 amount)` :将 **`amount`** 数量的代币从 **`from`** 地址发送到 **`to`** 地址,返回布尔值告知是否执行成功。触发 **`Transfer`** 事件。
**事件(定义中的 **`indexed`** 便于查找过滤):**
* `Transfer(address from, address to, uint256 value)` :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
* `Approval(address owner, address spender, uint256 value)` :当代币所有者授权别人使用代币时触发,即调用 **`approve`** 方法。
#### **元数据**
**一般除了上述必须实现的函数外,还有一些别的方法:**
* `name()` :返回代币名称
* `symbol()` :返回代币符号
* `decimals()` :返回代币小数点后位数
### **ERC20**
**来看下 ERC20 代币具体是怎么写的。**
**同样,OpenZepplin 提供了现成的合约代码:**
```
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
```
这里贴一个GitHub源码链接 [**OpenZepplin ERC20**](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
#### **函数概览**
```
constructor(name_, symbol_)
name()
symbol()
decimals()
totalSupply()
balanceOf(account)
transfer(to, amount)
allowance(owner, spender)
approve(spender, amount)
transferFrom(from, to, amount)
increaseAllowance(spender, addedValue)
decreaseAllowance(spender, subtractedValue)
_transfer(from, to, amount)
_mint(account, amount)
_burn(account, amount)
_approve(owner, spender, amount)
_spendAllowance(owner, spender, amount)
_beforeTokenTransfer(from, to, amount)
_afterTokenTransfer(from, to, amount)
```
****事件(同 IERC20)****
```
Transfer(from, to, value)
Approval(owner, spender, value)
```
#### **逐一分析**
* `constructor(string name, string symbol)` :设定代币的名称和符号。**`decimals`** 默认是 18 ,要修改成不同的值你应该重载它。这两个值是不变的,只在构造时赋值一次。
* `name()` :返回代币的名称。
* `symbol()` :返回代币的符号,通常是名称的缩写。
* `decimals()` :返回小数点后位数,通常是 18 ,模仿 Ether 和 wei 。要更改就重写它。
`totalSupply()、balanceOf(address account)、transfer(address to, uint256 amount)、 allowance(address owner, address spender)、approve(address spender, uint256 amount)、transferFrom(address from, address to, uint256 amount)` 都参考 IERC20 。
* `increaseAllowance(address spender, uint256 addedValue)` :以原子的方式增加 **`spender`** 额度。返回布尔值告知是否执行成功,触发 **`Approval`** 事件。
* `_transfer(address from, address to, uint256 amount)` :转账。这个内部函数相当于 **`transfer`** ,可以用于例如实施自动代币费用,削减机制等。触发 **`Transfer`** 事件。
* `_mint(address account, uint256 amount)` :铸造 **`amount`** 数量的代币给 **`account`** 地址,增加总发行量。触发 **`Transfer`** 事件,其中参数 **`from`** 是零地址。
* `_burn(address account, uint256 amount)` :从 **`account`** 地址中烧毁 **`amount`** 数量的代币,减少总发行量。触发 **`Transfer`** 事件,其中参数 **`to`** 是零地址。
* `_approve(address owner, uint256 spender, uint256 amount)` :设定允许 **`spender`** 花费 **`owner`** 的代币数量。这个内部函数相当于 **`approve`** ,可以用于例如为某些子系统设置自动限额等。
* `spendAllowance(address owner, address spender, uint256 amount)` :花费 **`amount`** 数量的 **`owner`** 授权 **`spender`** 的代币。在无限 allowance 的情况下不更新 allowance 金额。如果没有足够的余量,则恢复。可能触发 **`Approval`** 事件。
* `_beforeTokenTransfer(address from, address to, uint256 amount)` :在任何代币转账前的 Hook 。它包括铸币和烧毁。调用条件:
* **当 **`from`** 和 **`to`** 都不是零地址时,**`from` 手里 **`amount`** 数量的代币将发送给 **`to`** 。
* **当 **`from`** 是零地址时,将给 **`to`** 铸造 **`amount`** 数量的代币。**
* **当 **`to`** 是零地址时,**`from` 手里 **`amount`** 数量的代币将被烧毁。
* `from` 和 **`to`** 不能同时为零地址。
* `_afterTokenTransfer(address from, address to, uint256 amount)` :在任何代币转账后的 Hook 。它包括铸币和烧毁。调用条件:
* **当 **`from`** 和 **`to`** 都不是零地址时,**`from` 手里 **`amount`** 数量的代币将发送给 **`to`** 。
* **当 **`from`** 是零地址时,将给 **`to`** 铸造 **`amount`** 数量的代币。**
* **当 **`to`** 是零地址时,**`from` 手里 **`amount`** 数量的代币将被烧毁。
* `from` 和 **`to`** 不能同时为零地址。
#### **小结**
**ERC20 代码中的 **`_transfer`**、**`_mint`**、**`_burn`**、**`_approve`**、**`_spendAllowance`**、**`_beforeTokenTransfer`**、**`_afterTokenTransfer` 都是 **`internal`** 函数(其余为 **`public`** ),也就是说它们只能被派生合约调用。
## **从零开始,自己动手**
### **1.编写IERC20**
[**IERC20.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/IERC20.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
/// @dev 总发行量
function totoalSupply() external view returns (uint256);
/// @dev 查看地址余额
function balanceOf(address account) external view returns (uint256);
/// @dev 单地址转账
function transfer(address account, uint256 amount) external returns (bool);
/// @dev 查看被授权人代表所有者花费的代币余额
function allowance(address owner, address spender) external view returns (uint256);
/// @dev 授权别人花费你拥有的代币
function approve(address spender, uint256 amount) external returns (bool);
/// @dev 双地址转账
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @dev 发生代币转移时触发
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev 授权时触发
event Approval(address indexed owner, address indexed spender, uint256 value);
}
```
### **2.加上Metadata**
[**IERC20Metadata.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/IERC20Metadata.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
/// @dev 代币名称
function name() external view returns (string memory);
/// @dev 代币符号
function symbol() external view returns (string memory);
/// @dev 小数点后位数
function decimals() external view returns (uint8);
}
```
### **3.编写ERC20**
[**ERC20.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/ERC20.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
contract ERC20 is IERC20, IERC30Metadata {
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/// @dev 设定代币名称符号
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/// @dev 小数点位数一般为 18
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 substractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= substractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approval(owner, spender, currentAllowance - substractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender];
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
```
## **总结**
**ERC20 其实就是一种最常见的代币标准,它明确了同质化代币的经典功能并规范了开发者编写 token 时的代码,从而方便各种应用适配。**
ERC20解读
参考 OpenZepplin文档 和 以太坊官方开发者文档,结合自己的理解。
博客的 Markdown 编辑器暂不支持 Solidity 语法高亮,为了更好阅读代码,可以去 我的GitHub仓库 。
什么是ERC20
ERC20(Ethereum Request for Comments 20)一种代币标准。EIP-20 中提出。
ERC20 代币合约跟踪同质化(可替代)代币:任何一个代币都完全等同于任何其他代币;没有任何代币具有与之相关的特殊权利或行为。这使得 ERC20 代币可用于交换货币、投票权、质押等媒介。
为什么要遵守ERC20
EIP-20 中的动机:
允许以太坊上的任何代币被其他应用程序(从钱包到去中心化交易所)重新使用的标准接口。
以太坊上的所有应用都默认支持 ERC20 ,如果你想自己发币,那么你的代码必须遵循 ERC20 标准,这样钱包(如MetaMask)等应用才能将你的币显示出来。
代码实现
需要实现以下函数和事件:
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
使用 OpenZeppllin 提供的库能够轻松快速地构建 ERC20 Token 。
快速构建
这是一个 GLD token 。
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
通常,我们定义代币的发行量和代币名称及符号。
IERC20
先来看下 ERC20 的接口(IERC20),这方便我们在开发中直接定义 ERC20 代币。
同样地,OpenZepplin 为我们提供了相应的库,方便开发者导入即用。
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
EIP 中定义的 ERC20 标准接口:
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
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);
}
逐一分析
函数:
totalSupply() :返回总共的代币数量。
balanceOf(address account) :返回 account 地址拥有的代币数量。
transfer(address to, uint256 amount) :将 amount 数量的代币发送给 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
allowance(address owner, address spender) :返回授权花费者 spender 通过 transferFrom 代表所有者花费的剩余代币数量。默认情况下为零。当 approve 和 transferFrom 被调用时,值将改变。
approve(address spender, uint256 amount) :授权 spender 可以花费 amount 数量的代币,返回布尔值告知是否执行成功。触发 Approval 事件。
transferFrom(address from, address to, uint256 amount) :将 amount 数量的代币从 from 地址发送到 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
事件(定义中的 indexed 便于查找过滤):
Transfer(address from, address to, uint256 value) :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
Approval(address owner, address spender, uint256 value) :当代币所有者授权别人使用代币时触发,即调用 approve 方法。
元数据
一般除了上述必须实现的函数外,还有一些别的方法:
name() :返回代币名称
symbol() :返回代币符号
decimals() :返回代币小数点后位数
ERC20
来看下 ERC20 代币具体是怎么写的。
同样,OpenZepplin 提供了现成的合约代码:
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
这里贴一个GitHub源码链接 OpenZepplin ERC20
函数概览
constructor(name_, symbol_)
name()
symbol()
decimals()
totalSupply()
balanceOf(account)
transfer(to, amount)
allowance(owner, spender)
approve(spender, amount)
transferFrom(from, to, amount)
increaseAllowance(spender, addedValue)
decreaseAllowance(spender, subtractedValue)
_transfer(from, to, amount)
_mint(account, amount)
_burn(account, amount)
_approve(owner, spender, amount)
_spendAllowance(owner, spender, amount)
_beforeTokenTransfer(from, to, amount)
_afterTokenTransfer(from, to, amount)
事件(同 IERC20)
Transfer(from, to, value)
Approval(owner, spender, value)
逐一分析
constructor(string name, string symbol) :设定代币的名称和符号。decimals 默认是 18 ,要修改成不同的值你应该重载它。这两个值是不变的,只在构造时赋值一次。
name() :返回代币的名称。
symbol() :返回代币的符号,通常是名称的缩写。
decimals() :返回小数点后位数,通常是 18 ,模仿 Ether 和 wei 。要更改就重写它。
totalSupply()、balanceOf(address account)、transfer(address to, uint256 amount)、 allowance(address owner, address spender)、approve(address spender, uint256 amount)、transferFrom(address from, address to, uint256 amount) 都参考 IERC20 。
increaseAllowance(address spender, uint256 addedValue) :以原子的方式增加 spender 额度。返回布尔值告知是否执行成功,触发 Approval 事件。
_transfer(address from, address to, uint256 amount) :转账。这个内部函数相当于 transfer ,可以用于例如实施自动代币费用,削减机制等。触发 Transfer 事件。
_mint(address account, uint256 amount) :铸造 amount 数量的代币给 account 地址,增加总发行量。触发 Transfer 事件,其中参数 from 是零地址。
_burn(address account, uint256 amount) :从 account 地址中烧毁 amount 数量的代币,减少总发行量。触发 Transfer 事件,其中参数 to 是零地址。
_approve(address owner, uint256 spender, uint256 amount) :设定允许 spender 花费 owner 的代币数量。这个内部函数相当于 approve ,可以用于例如为某些子系统设置自动限额等。
spendAllowance(address owner, address spender, uint256 amount) :花费 amount 数量的 owner 授权 spender 的代币。在无限 allowance 的情况下不更新 allowance 金额。如果没有足够的余量,则恢复。可能触发 Approval 事件。
_beforeTokenTransfer(address from, address to, uint256 amount) :在任何代币转账前的 Hook 。它包括铸币和烧毁。调用条件:
当 from 和 to 都不是零地址时,from 手里 amount 数量的代币将发送给 to 。
当 from 是零地址时,将给 to 铸造 amount 数量的代币。
当 to 是零地址时,from 手里 amount 数量的代币将被烧毁。
from 和 to 不能同时为零地址。
_afterTokenTransfer(address from, address to, uint256 amount) :在任何代币转账后的 Hook 。它包括铸币和烧毁。调用条件:
当 from 和 to 都不是零地址时,from 手里 amount 数量的代币将发送给 to 。
当 from 是零地址时,将给 to 铸造 amount 数量的代币。
当 to 是零地址时,from 手里 amount 数量的代币将被烧毁。
from 和 to 不能同时为零地址。
小结
ERC20 代码中的 _transfer、_mint、_burn、_approve、_spendAllowance、_beforeTokenTransfer、_afterTokenTransfer 都是 internal 函数(其余为 public ),也就是说它们只能被派生合约调用。
从零开始,自己动手
1.编写IERC20
IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
/// @dev 总发行量
function totoalSupply() external view returns (uint256);
/// @dev 查看地址余额
function balanceOf(address account) external view returns (uint256);
/// @dev 单地址转账
function transfer(address account, uint256 amount) external returns (bool);
/// @dev 查看被授权人代表所有者花费的代币余额
function allowance(address owner, address spender) external view returns (uint256);
/// @dev 授权别人花费你拥有的代币
function approve(address spender, uint256 amount) external returns (bool);
/// @dev 双地址转账
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @dev 发生代币转移时触发
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev 授权时触发
event Approval(address indexed owner, address indexed spender, uint256 value);
}
2.加上Metadata
IERC20Metadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
/// @dev 代币名称
function name() external view returns (string memory);
/// @dev 代币符号
function symbol() external view returns (string memory);
/// @dev 小数点后位数
function decimals() external view returns (uint8);
}
3.编写ERC20
ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
contract ERC20 is IERC20, IERC30Metadata {
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/// @dev 设定代币名称符号
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/// @dev 小数点位数一般为 18
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 substractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= substractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approval(owner, spender, currentAllowance - substractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender];
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
总结
ERC20 其实就是一种最常见的代币标准,它明确了同质化代币的经典功能并规范了开发者编写 token 时的代码,从而方便各种应用适配。
学分: 39
分类: 以太坊
标签:
ERC20
点赞 3
收藏 5
分享
Twitter分享
微信扫码分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
你可能感兴趣的文章
花式发币法之发行各类 ERC20 代币
3968 浏览
Michael.W基于Foundry精读Openzeppelin第39期——ERC20.sol
506 浏览
教程:如何在没有 Web 界面的情况下创建 ERC20桥
1574 浏览
一个简单的ERC20代币空投合约
2653 浏览
发布一款ERC20代币,并开发成Dapp
1548 浏览
Aptos合约开发之部署ERC20合约
3944 浏览
相关问题
请教下大家,Swap如何实现卖币手续费
2 回答
如何从发起部署的地址中,转移一部分代币到已经部署的合约地址中,麻烦那位大佬看一下
5 回答
空投的默克尔树如何防止生日攻击?
2 回答
bsc链上的erc20合约,要求只有一点买卖的时候2%兑换成bnb发送到营销钱包,现在的问题是添加流动性会一直报错Fail with error 'TransferHelper::transferFrom: transferFrom failed'
2 回答
eth中如何判断合约是erc20合约
2 回答
寻找使用Vyper部署的带有交易税的ERC20代币模版
1 回答
0 条评论
请先 登录 后评论
Confucian
关注
贡献值: 57
学分: 83
Keep Learning
文章目录
关于
关于我们
社区公约
学分规则
Github
伙伴们
DeCert
ChainTool
GCC
合作
广告投放
发布课程
联系我们
友情链接
关注社区
Discord
Youtube
B 站
公众号
关注不错过动态
微信群
加入技术圈子
©2024 登链社区 版权所有 |
Powered By Tipask3.5|
粤公网安备 44049102496617号
粤ICP备17140514号
粤B2-20230927
增值电信业务经营许可证
×
发送私信
请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!
发给:
内容:
取消
发送
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
取消
举报
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
什么是ERC-20?关于ERC代币你应该了解的知识点 - 知乎
什么是ERC-20?关于ERC代币你应该了解的知识点 - 知乎首发于AAX学院切换模式写文章登录/注册什么是ERC-20?关于ERC代币你应该了解的知识点AAX学院高流动,低点差——尽在aax.com你应该听说过ERC-20代币,特别是如果你关注过2017年ICO热潮期间的加密领域。然而,除了ERC-20之外,还有许多其他的以太坊代币标准,比如ERC-721和ERC-223,它们给代币提供了更多的用例。在这篇文章中,作为以太坊区块链之旅的一部分,我们主要探索最重要的ERC代币标准。“ERC”是什么意思?ERC是Ethereum Request for Comment的缩写,用于对代币和以太坊生态系统提出改进建议。提交ERC后,以太坊社区将对其进行评估,并决定是否接受或拒绝该建议。获得绿灯后,ERC将被正式确定为以太坊改进建议(EIP)。虽然ERC大多是初始和非正式的建议,但EIP总是由以太坊核心开发者进行审核和评估。说到这里,”ERC “这个词在加密货币社区中广为人知,它是以太坊网络上代币的标准。简而言之,代币标准是用来定义数据和实现它的每个代币的功能。代币的标准化使得创作者更容易发行币,并将其与应用程序集成。ERC-20范例: Tether (USDT), Chainlink (LINK), AAX Token (AAB)ERC-20是以太坊生态系统中最流行的代币标准,也是整个加密货币行业中最流行的代币标准。ERC-20是由以太坊联合创始人Vitalik Buterin在2015年6月提出的,它是一个简单的接口,允许开发者在以太坊区块链之上创建他们的代币,并将其与第三方应用程序(如钱包和交易所)集成。除了允许创建者使用简单的功能,比如限制他们的币的总供应量,ERC-20代币、去中心化应用(DApps)和智能合约之间也有直接的互动。需要强调的是,ERC-20代币是可以互换的资产。就像百元大钞或标准金条一样,可互换代币是具有等值单位的相同资产。由于创建ERC-20代币很容易,大多数加密项目在2017年的ICO热潮中使用该标准来发行他们的原生币,并将其出售给出资者。因此,ERC-20是加密行业最广泛接受的代币标准,大多数数字资产钱包、交易所(包括AAX)和其他服务都支持该标准。ERC223范例:暂无ERC-223是以太坊生态系统中的一个可互换代币标准,其主要目标是解决ERC-20的一些问题。虽然ERC-20在加密项目和用户中非常受欢迎,但它允许人们将加密货币发送到智能合约而不是钱包。因此,一些用户由于合约失败或其他原因而失去了他们的资金。为了解决这个问题,ERC-223有一个功能,在用户不小心将代币发送到智能合约的情况下,会自动提醒用户。这样的交易会被自动取消,让用户收回资金(但还是要支付矿工费)。虽然它向下兼容ERC-20币,但ERC-223的特点是比之更低廉的矿工费。然而,尽管ERC-223具有优势,但它未能被以太坊社区采用,也尚未有加密项目使用该代币标准。ERC-721范例: CryptoKitties, Sorare与ERC-20和ERC-223相反,ERC-721是一个不可替代的代币(NFT)标准。这里的每个代币不是相同的硬币,而是独一无二的,具有自己的标识符,便于通过区块链进行验证。虽然可互换代币具有类似于标准金条或同值美元钞票的功能,但ERC-721币更像是艺术品或其他(复杂的)手工制作的物品,每件物品都是独一无二的,在某些方面与其他物品不同。虽然它们有多种应用,但NFT最受欢迎的用例是在区块链游戏解决方案中。通过非同质的代币,区块链游戏玩家可以收集、拥有和交易独特的游戏物品,如武器、角色、衣服、坐骑和车辆。此外,ERC-721代币标准允许创作者在多个区块链游戏和应用中集成NFT,让游戏玩家无论在哪里玩都能使用他们的数字收藏品。ERC-1155范例:EnjinERC-1155是一种混合代币标准,允许开发人员在一个智能合约下创建无限的可替代代币和不可替代代币。开发者在使用ERC-721时必须为每个NFT创建一个新的智能合约,而在使用ERC-1155时,他们只需要为非可替代代币和可互替代代币部署一个智能合约,从而缩短了开发时间,并最大限度地减少了创建者使用的资源。在区块链游戏中,这使得加密货币项目可以使用单一的智能合约来发行他们的游戏内货币作为可替代的代币,同时让用户在参与游戏的过程中收集NFT项目。关于AAX学院AAX是由LSEG Technology公司提供技术支持的数字资产交易所。AAX学院是AAX打造的一档用户教育频道,旨在帮助更多用户学习新手教程和了解到关于区块链的基础知识。 发布于 2020-09-22 08:38首次代币发行(ICO)数字化资产token赞同 51 条评论分享喜欢收藏申请转载文章被以下专栏收录AAX学院带来最前沿的区块链资讯知识,探究区块链背后
ERC20 - 廖雪峰的官方网站
ERC20 - 廖雪峰的官方网站
Index
廖雪峰的官方网站
Blog
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
More
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
Profile
Passkey
Sign Out
Sign In
English
简体中文
Index
区块链教程
比特币
区块链原理
P2P交易原理
私钥
公钥和地址
签名
挖矿原理
可编程支付原理
多重签名
UTXO模型
Segwit地址
HD钱包
钱包层级
助记词
地址监控
以太坊
账户
区块结构
交易
智能合约
编写合约
部署合约
调用合约
编写Dapp
常用合约
ERC20
Wrapped Ether
关注公众号不定期领红包:
加入知识星球社群:
关注微博获取实时动态:
ERC20
Last updated: ...
/
Reads: 59011
Edit
ERC20是以太坊定义的一个合约接口规范,符合该规范的合约被称为以太坊代币。
一个ERC20合约通过mapping(address => uint256)存储一个地址对应的余额:
contract MyERC20 {
mapping(address => uint256) public balanceOf;
}
如果要在两个地址间转账,实际上就是对balanceOf这个mapping的对应的kv进行加减操作:
contract MyERC20 {
mapping(address => uint256) public balanceOf;
function transfer(address recipient, uint256 amount) public returns (bool) {
// 不允许转账给0地址:
require(recipient != address(0), "ERC20: transfer to the zero address");
// sender的余额必须大于或等于转账额度:
require(balanceOf[msg.sender] >= amount, "ERC20: transfer amount exceeds balance");
// 更新sender转账后的额度:
balanceOf[msg.sender] -= amount;
// 更新recipient转账后的额度:
balanceOf[recipient] += amount;
// 写入日志:
emit Transfer(sender, recipient, amount);
return true;
}
}
安全性
早期ERC20转账最容易出现的安全漏洞是加减导致的溢出,即两个超大数相加溢出,或者减法得到了负数导致结果错误。从Solidity 0.8版本开始,编译器默认就会检查运算溢出,因此,不要使用早期的Solidity编译即可避免溢出问题。
没有正确实现transfer()函数会导致交易成功,却没有任何转账发生,此时外部程序容易误认为已成功,导致假充值:
function transfer(address recipient, uint256 amount) public returns (bool) {
if (balanceOf[msg.sender] >= amount) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
} else {
return false;
}
}
实际上transfer()函数返回bool毫无意义,因为条件不满足必须抛出异常回滚交易,这是ERC20接口定义冗余导致部分开发者未能遵守规范导致的。
ERC20另一个严重的安全性问题来源于重入攻击:
function transfer(address recipient, uint256 amount) public returns (bool) {
require(recipient != address(0), "ERC20: transfer to the zero address");
uint256 senderBalance = balanceOf[msg.sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
// 此处调用另一个回调:
callback(msg.sender);
// 更新转账后的额度:
balanceOf[msg.sender] = senderBalance - amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
先回调再更新的方式会导致重入攻击,即如果callback()调用了外部合约,外部合约回调transfer(),会导致重复转账。防止重入攻击的方法是一定要在校验通过后立刻更新数据,不要在校验-更新中插入任何可能执行外部代码的逻辑。
Comments
Make a comment
Sign in to
make a comment
Index
区块链教程
比特币
区块链原理
P2P交易原理
私钥
公钥和地址
签名
挖矿原理
可编程支付原理
多重签名
UTXO模型
Segwit地址
HD钱包
钱包层级
助记词
地址监控
以太坊
账户
区块结构
交易
智能合约
编写合约
部署合约
调用合约
编写Dapp
常用合约
ERC20
Wrapped Ether
廖雪峰的官方网站
©Copyright 2019-2021
Powered by iTranswarp
Feedback
License
ERC-20 - 维基百科,自由的百科全书
ERC-20 - 维基百科,自由的百科全书
跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页分类索引特色内容新闻动态最近更改随机条目资助维基百科
帮助
帮助维基社群方针与指引互助客栈知识问答字词转换IRC即时聊天联络我们关于维基百科
搜索
搜索
创建账号
登录
个人工具
创建账号 登录
未登录编辑者的页面 了解详情
贡献讨论
目录
移至侧栏
隐藏
序言
1参考文献
开关目录
ERC-20
4种语言
EnglishFrançaisMagyarPolski
编辑链接
条目讨论
简体
不转换简体繁體大陆简体香港繁體澳門繁體大马简体新加坡简体臺灣正體
阅读编辑查看历史
工具
工具
移至侧栏
隐藏
操作
阅读编辑查看历史
常规
链入页面相关更改上传文件特殊页面固定链接页面信息引用本页获取短URL下载二维码维基数据项目
打印/导出
下载为PDF可打印版
维基百科,自由的百科全书
ERC-20是以太坊区块链上的一种智能合约协议标准[1]。根据Etherscan.io的资料,截至2018年11月19日,一共有142273种加密货币兼容ERC-20[2]。
参考文献[编辑]
^ ERC-20 Token Standard - The Ethereum Wiki. Theethereum.wiki. [2017-08-30]. (原始内容存档于2017-08-29) (英语).
^ etherscan.io. Etherscan Token Tracker Page. [2019-11-19]. (原始内容存档于2018-12-19) (英语).
取自“https://zh.wikipedia.org/w/index.php?title=ERC-20&oldid=68903491”
分类:另类货币区块链密码货币隐藏分类:CS1英语来源 (en)
本页面最后修订于2021年12月1日 (星期三) 10:42。
本站的全部文字在知识共享 署名-相同方式共享 4.0协议之条款下提供,附加条款亦可能应用。(请参阅使用条款)
Wikipedia®和维基百科标志是维基媒体基金会的注册商标;维基™是维基媒体基金会的商标。
维基媒体基金会是按美国国内税收法501(c)(3)登记的非营利慈善机构。
隐私政策
关于维基百科
免责声明
行为准则
开发者
统计
Cookie声明
手机版视图
开关有限宽度模式
ERC-20 | 欧易
20 | 欧易交易所Web3 钱包买币快捷买币流程简单,快速成交C2C 买币0 交易费轻松交易,支持超 100 种支付方式第三方支付Banxa, Simplex等发现市场查看最新行情和交易大数据机会发掘最热、最新币种,及时捕捉市场机会交易交易类型闪兑币币兑换,0 费率,无滑点币币轻松买卖数字货币合约交易永续和交割合约,灵活使用杠杆杠杆借币交易期权利用市场波动,赚取收益,降低交易风险交易工具策略交易多种智能策略,助您轻松交易策略广场创建策略流动性市场为交割价差、自定义多腿策略和大宗交易带来深度流动性价差速递询价单金融赚币持币生币, 赚取收益简单赚币链上赚币结构化产品借贷质押数字资产,满足您的投资和消费需求Jumpstart抢先发现全球优质新项目公链X1探索 X1进入 Web3 的世界X1点燃创意、引领创新测试网浏览器测试网链上数据X1 生态探索 X1 DApp开发者无限扩容开发者文档查看技术文档测试网水龙头获取测试网 OKB预言机获取价格数据GitHub探索 X1 仓库官方应用基础建设产品跨链桥在以太坊与 X1 间进行资产跨链OKTC探索 OKTCEVM 和 IBC 兼容公链OKTC去中心化的 L1 区块链网络OKTC 浏览器主网链上数据测试网浏览器测试网链上数据官方应用基础建设产品IBC 转账在 Cosmos 网络之间进行转账兑换在 OKTC 上交易代币流动性质押质押 OKT 获得 stOKTMultisig safe多签数字资产钱包开发者构建未来预言机获取价格数据开发者分红返还 Gas 费用,获得 OKTSubgraph索引和查询链上数据GitHub探索 OKTC 仓库测试网水龙头获取测试网 OKT开发者文档查看技术文档用户社区信任过程,共享成长Galxe 活动领先的 Web3 数据网络QuestN 频道Web3 用户一站式社群机构客户机构首页为机构客户提供最强劲、最完整的数字货币交易解决方案流动性市场支持场外交易,为专业交易员和机构用户提供流动性API超低延迟的 API 无缝连接您的数据和操作尊享借币提高资金利用率经纪商项目享受世界一流的市场深度,获得高额的佣金回赠资管子账户统一管理子账户,让交易变得更轻松、更安全、更实惠历史行情数据K线图、交易汇总、订单表数据等信息尽在掌握新手学院更多产品OKB资金安全Status储备金证明其他奖励中心邀请好友节点计划OKX Ventures使用 TradingView 交易登录注册用户支持帮助中心我的客服工单加入欧易社群Discord学院区块链词典文章Web3ERC-20欧易发布于 2022年6月30日更新于 2023年11月08日介绍ERC-20和ERC-721之前,先介绍下ERC是什么。
一、ERC-20为开发者提供了,在以太坊一键发行通证的功能:
ERC是Ethereum Request for Comment的缩写,即开发者对于以太坊通证和生态提出的建议,更专业的解释就是关于通证设计具体标准的代码协议。所以直观理解,ERC-20也就是以太坊的第20号通证标准协议。
进一步解释,可以类比一下,正如TCP/IP协议是用来规范互联网的通讯传输,ERC-20协议是用来规范以太坊平台数据通讯的标准之一。所以,如果要在以太坊上发行Token,就需要遵守以太坊的ERC-20协议,这个协议主要包含了:确定Token的名称、简称、总量、精确小数点后多少位等等。
目前,ERC-20已经成为以太坊网络中最主流的通证标准,目前市面上95%以上的通证,都是基于这一标准开发的。该标准允许开发者在以太坊上,以较低的门槛发行专属于自己的通证,并且为开发者提供了一套标准化、简单化的设计功能,具体有:
1、设定通证名称
2、设定通证总量
3、规定小数点位数
4、规范如何批准通证交易
5、如何访问数据
6、允许查看各地址中ERC20通证数目以及通证总量
7、一定条件下,允许第三方账户使用某账户中的通证资产
8、允许通证和兼容ETH的智能合约及钱包服务等第三方个体兼容
9、其他简单的函数功能等等。
二、ERC-20已成为同质化通证的主流,ERC-721则是NFT的主流
很显然,很多不懂编程的计算机爱好者,也可以通过复制ERC-20标准代码,在较短的时间内发行一种新的通证,这也使得各类加密资产在2017年夏季以来如雨后春笋版涌现。ERC-20标准也成了以太坊通证标准的模板,ERC-223、ERC-621和ERC-777等标准都是ERC-20的改进版本。
需要提及的是,ERC-20标准无法与NFT兼容,因为NFT是非同质化通证,和按照同质化设计标准为底层的ERC-20协议并不匹配。所以,为在以太坊上发行NFT资产的ERC-721标准随即问世。
另外,需要注意的是,ERC-20作为一种标准和协议的同时,也为加密圈资产提供多重功能,它也是一种智能合约,为用户提供链上资产存储和转账的功能。按照这样的理解,它更像是一个去中心化的网络,为链上的资产流动提供载体。当然,这也是得益于它是一项标准化的协议,才能担此大任,因为绝大多数以此标准铸造的资产的互通性、兼容性很高,链上的无缝衔接遇到的障碍更小。
三、关于用ERC-20等协议转账USDT等问题的梳理
对于我们普通用户来说,ERC-20和我们关联最大的,是稳定币USDT的转账环节。这部分做一下重点介绍:
众所周知,USDT是加密圈的价值媒介和价值尺度,不同类型通证间的交易需要USDT作为中介。但是,USDT的接收、存储和转账都需要依托具体的去中心化网络。在早期,USDT主要是在比特币的Omni协议上完成一站式的发行、交易和存储。但是,到了2018年以后,随着以太坊生态的爆火,USDT背后的泰达公司选择拥抱生态活跃度更高的以太坊,而众多协议中的首选,自然是通用度最高的ERC-20协议。
另外,在USDT等中心化稳定币资产转账方面,ERC-20网络相较Omni协议有着多重明显优势:尽管同样收取矿工费但是转账速度更快、稳定性更强,安全性也更有保证。
随着以太坊网络拥堵的加剧,以及ETH价格的上涨,使用ERC-20标准转账的成本水涨船高,很多用户难堪其重。针对这一痛点,波场公链网络开发出了免收矿工费的TRC-20协议,用以抢占ERC-20的市场份额。但是,TRC-20标准的安全性,还是弱于ERC-20。在转账协议的选择上,用户需要结合转账速度、成本费用和总体金额,以及对于风险的承受度,进行综合考虑。
相关推荐查看更多Web3该概念由Polkadot 创始人 Gavin 博士提出,Gavin 认为,Web3 是一组包容性协议,为应用程序制造商提供构建块。这些构建块取代了传统的 Web 技术,如 HTTP,AJAX,MySQL,提供了一种创建应用程序的全新方式。这些技术为用户提供了强大且可验证的保证,从2023年9月26日行业热词EIP-1559EIP-1559提议变更了以太坊的费用模式,该提案通过烧掉ETH支付的费用而不是分配给矿工来减少交易费用的波动性。 EIP-1559改变了以第一价拍卖为基础的Gas fee计算逻辑。第一拍卖即价高者得,用户为了让矿工及时打包自己的交易,需要加价支付矿工费,出价越高,被优先打2023年11月8日区块链概念比特币ETF简介什么是比特币ETF? 比特币ETF,即比特币交易所交易基金,可以使交易者通过传统股票市场获得比特币风险敞口,而无需直接持有比特币。按照具体交易产品的不同,可以分为比特币现货ETF、比特币期货ETF。 比特币ETF有什么优势? 相比目前市场上以GBTC为代表的主流数字资产信托2023年11月17日行业热词策略交易模式策略交易是一种帮助用户进行自动交易的工具。相比手动交易,策略交易有降低交易风险、减少操作成本、掌控交易时机等优势,成为深受投资者喜爱的一种交易模式。 目前欧易平台为用户提供了网格、DCA、冰山策略等多种不同的策略交易模式,是市面上最为成熟的提供多套策略的平台之一。此外,欧易提供策2023年11月18日交易概念统一交易账户介绍统一交易账户(Unified Account)是欧易面向广大用户推出的新一代交易系统,支持在一个账户中使用多币种资产同时交易现货和各类衍生品,这将会为用户的交易提供极大的便利,不再需要在多个账户之间进行资金划转;且不同业务线的盈亏可以互相抵消、有效提升了用户的资金利用率。统一交易2023年7月4日交易概念什么是TUSD?概述 TrueUSD(简称TUSD)是一种基于区块链技术的加密货币,旨在通过提供一种稳定的代币,解决许多加密货币的价格波动性问题。TrueUSD由TrustToken发行,每个TUSD代币都与美元一比一挂钩,因此其价格保持稳定。与其他加密货币不同,TrueUSD通过将美元存入银行2023年3月29日
©2017 - 2024 OKX.COM简体中文English繁體中文Français (Afrique)РусскийTiếng ViệtBahasa IndonesiaTürkçeDeutschItalianoPolskiPortuguês (Brasil)Português (Portugal)Español (España)Español (Latinoamérica)ČeštinaRomânăУкраїнськаالعربيةNederlands关于欧易关于我们职业机会联系我们服务条款隐私保护免责声明廉正举报执法请求欧易 App产品快捷买币C2C 交易闪兑交易赚币OKTCWeb3 钱包Web3 市场数字货币计算器策略交易浏览所有数字货币新手学院TradingView服务节点计划V5 API历史行情数据费率标准上币申请C2C 认证商家申请用户支持帮助中心官方验证公告加入欧易社群买币购买 USDC购买泰达币 (USDT)购买比特币 (Bitcoin)购买以太币 (Ethereum)购买 ADA购买 Solana购买 MATIC购买 Litecoin购买 XRP数字货币计算器BTC 兑换 CNYETH 兑换 CNYUSDT 兑换 CNYSOL 兑换 CNYXRP 兑换 CNY交易BTC USDCETH USDCBTC USDTETH USDTMATIC USDTLTC USDTSOL USDTXRP USDT比特币 (BTC) 价格以太坊 (ETH) 价格Cardano 价格Solana 价格XRP 价格欧易,随时随地交易注册扫码下载欧易