2つの概念
- ERC (イーサリアムのコメント要求) イーサリアムのコメント要求
- EIP (Ethereum Improvement Proposals) イーサリアム改善提案
ERC と EIP は、イーサリアムをより完全にするために使用されます。ERC では多くの標準が提案されていますが、最も一般的に使用されている標準はトークン標準です。
詳細については、https://eips.ethereum.org/ercを参照してください。
共通の ERC 標準
ERC-20 | トークン規格 |
---|---|
ERC-721 | 代替不可能なトークン標準 |
ERC-165 | 標準インターフェース検出 |
ERC-777 | トークン規格 |
ERC-1155 | マルチトークン標準 |
ERC-20
主に均質なトークン規格(異なる人が保有するトークンの価値は等しい)を指します。
ERC-20規格には主に6つの関数と2つのイベントがあり、
この6つの関数が表す意味は、
totalSupply:総流通
残高Of:口座残高
transfer:振替
transferFrom:認可のための振込
approve:認可
手当:所有者が利用者残高を認可する
詳細については、https://eips.ethereum.org/EIPS/eip-20を参照してください。
ERC20標準トークンの実装
ERC20 標準トークンを検出したい場合は、ERC20 標準インターフェイスに関数を実装する必要があります。
まずERC20標準インターフェースを書きます
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address _owner) external view returns (uint256 balance);
function transfer(address _to, uint256 _value) external returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
function approve(address _spender, uint256 _value) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
//_from和_to两个参数有indexed关键字修饰,表示这些参数可以作为过滤条件来搜索事件。
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
その後、ERC20標準トークンを実装します
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
contract ERC20 is IERC20{
string ercName;
string ercSymbol;
uint8 ercDecimals;
uint256 ercTotalSupply;
mapping(address=>uint256) ercBalances;
//一个人可以有多个委托人:授权者=>被授权者=>授权金额
mapping (address=>mapping (address=>uint256)) ercAllowance;
//合约部署者
address public owner;
constructor(string memory _name, string memory _symbol,uint8 _decimals){
ercName=_name;
ercSymbol=_symbol;
ercDecimals=_decimals;
owner=msg.sender;
}
//token名称
function name() override external view returns (string memory){
return ercName;
}
//token符号
function symbol() override external view returns (string memory){
return ercSymbol;
}
//token可以拆分到的精度
function decimals() override external view returns (uint8){
return ercDecimals;
}
//token发行总量
function totalSupply() override external view returns (uint256){
return ercTotalSupply;
}
//账户余额
function balanceOf(address _owner) override external view returns (uint256 balance){
return ercBalances[_owner];
}
//给某人转账
function transfer(address _to, uint256 _value) override external returns (bool success){
require(_value>0,"_value must >0");
require(_to!=address(0),"_to is null");
require(ercBalances[msg.sender]>=_value,"user's balance not enough");
ercBalances[msg.sender]-=_value;
ercBalances[_to]+=_value;
emit Transfer(msg.sender, _to, _value);
return true;
}
//被授权用户用我的token转账;_from: 授权者,_to:转给谁
function transferFrom(address _from, address _to, uint256 _value) override external returns (bool success){
require(ercBalances[_from] >= _value,"user's balance not enough");
require(ercAllowance[_from][msg.sender]>=_value,"approve's balance not enough");
require(_value>0,"_value must > 0");
require(_to!=address(0),"_to is null");
ercBalances[_from]-=_value;
ercBalances[_to]+=_value;
ercAllowance[_from][msg.sender]-=_value;
emit Transfer(_from, _to, _value);
return true;
}
//授权其他用户可以花费我多少token
function approve(address _spender, uint256 _value) override external returns (bool success){
// require(_value>0,"value must >0");//让_value可以等于0,当其为0时表示收回授权
require(_spender!=address(0),"_spender can not be null");
require(ercBalances[msg.sender]>=_value,"user's balance not enough");
ercAllowance[msg.sender][_spender]=_value;
emit Approval(msg.sender, _spender, _value);
return true;
}
//获取授花费的余额token
function allowance(address _owner, address _spender) override external view returns (uint256 remaining){
return ercAllowance[_owner][_spender];
}
//代币发行机制
function mint(address _to,uint256 _value) public{
require(msg.sender==owner,"only owner can mint");
require(_value>0,"_value must > 0");
require(_to!=address(0),"_to is invalid");
ercBalances[_to]+=_value;
ercTotalSupply+=_value;
emit Transfer(address(0), _to, _value);
}
}
ERC165
これは標準インターフェイス検出の標準であり、コントラクトが仕様に準拠しているかどうかを検出するために使用されます。
注意:函数选择器:
函数参数只保留类型,计算 hash("函数名(类型1, 类型2, ...)"),并取哈希结果的前4个字节
たとえば、次の関数の関数セレクターは次のとおりです。calculate hash("Transfer(address,uint256)")、ハッシュ結果の最初の 4 バイトを取得します。
function Transfer(address to,uint256 value){
//函数体
}
注意:接口ID:
将一个接口里面的所有函数选择器做异或处理,得到接口的ID
インターフェイスが ERC165 をサポートしているかどうかを確認するにはどうすればよいですか?
ERC-721
主に代替不可能なトークン規格を指します(アートワークなど、人によって保有されるトークンの価値が異なります)。