以太坊代币标准ERC20、ERC165、ERC721

news2024/11/28 5:50:39

两个概念

  • ERC(Ethereum Request for Comment) 以太坊意见征集稿
  • EIP(Ethereum Improvement Proposals)以太坊改进提案

ERC和EIP用于使得以太坊更加完善;在ERC中提出了很多标准,用的最多的标准就是它的Token标准;
有哪些标准详细见https://eips.ethereum.org/erc

常见ERC标准

ERC-20Token Standard
ERC-721Non-Fungible Token Standard
ERC-165Standard Interface Detection
ERC-777Token Standard
ERC-1155Multi Token Standard

ERC-20

主要是指同质化代币标准(不同人持有的一个代币是等值的)。
ERC-20标准中主要有6个函数和两个事件
在这里插入图片描述
其中这6个函数表达的意义是:
totalSupply:总发行量
balanceOf:账户余额
transfer:转账
transferFrom:针对授权进行转账
approve:授权
allowance:owner授权给spender余额
具体的详细见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个字节
举例,如下函数的函数选择器是:计算hash(“Transfer(address,uint256)”),并取哈希结果的前4个字节

function Transfer(address to,uint256 value){
	//函数体
}

注意:接口ID:
将一个接口里面的所有函数选择器做异或处理,得到接口的ID

如何判断一个接口支持了ERC165?

ERC-721

主要是指非同质化代币标准(不同人持有的一个代币的价值不一样,如,艺术品)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1042061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

预制菜行业数据分析(京东数据挖掘)

最近一段时间,关于预制菜进校园事件的讨论热度高涨。而这两天,核酸大王“张核子”转行开预制菜公司卖方便米饭的消息又被传出,直接让预制菜市场饱受关注。 “预制菜是近两年的风口”,这个结论鲸参谋早在以往的内容中专门讨论过&a…

Java 18的未来:新特性和编程实践

文章目录 引言新特性预览1. 基于值的类的进一步改进2. 模式匹配的增强3. 新的垃圾回收器4. 扩展的模块系统5. 更强大的异步编程 编程实践示例1:基于值的类示例2:模式匹配的增强示例3:新的垃圾回收器 结论 🎉欢迎来到Java学习路线专…

python机器学习融合模型:Stacking与Blending(附代码)

1 堆叠法Stacking 一套弱系统能变成一个强系统吗? 当你处在一个复杂的分类问题面前时,金融市场通常会出现这种情况,在搜索解决方案时可能会出现不同的方法。 虽然这些方法可以估计分类,但有时候它们都不比其他分类好。在这种情况…

[WUSTCTF2020]颜值成绩查询 布尔注入二分法

这道题很简单 就是sql注入 我们来学习一下如何写盲注脚本 ?stunum1 ?stunum123 正确回显 100 错误 显示 not 。。。 这里很显然就是盲注了 我们来写个语句查询 if(ascii(substr(database(),1,1))>1,1,0)发现回显了 我们可以开始编写脚本跑了 import requests impor…

DeepMind 利用无监督学习开发 AlphaMissense,预测 7100 万种基因突变

类基因组共有 31.6 亿个碱基对,无时无刻不在经历复制、转录和翻译,也随时有着出错突变的风险。 错义突变是基因突变中的一种常见形式,然而人类目前只观察到了其中的一小部分,能够解读的更是只有 0.1%。 准确预测错义突变的作用&am…

Windows10/11显示文件扩展名 修改文件后缀名教程

前言 写这篇文章的原因是由于我分享的教程中的文件、安装包基本都是存在阿里云盘的,下载后需要改后缀名才能使用。 但是好多同学不会改。。 Windows 10 随便打开一个文件夹,在上方工具栏点击 “查看”点击 “查看” 后下方会显示更详细的工具栏然后点…

剪映软件专业版的操作与使用,电脑版与手机版APP同步讲解

一、教程描述 什么是剪映?抖音官方推出的一款视频编辑工具,用于短视频的剪辑制作和在线发布,主要在手机端使用,同时支持PC端,操作简单易上手,功能也十分强大,使用过剪映的用户,都将…

ViT细节与代码解读

最近看到两篇解读ViT很好的文章,备忘记录一下: 先理解细节 1:再读VIT,还有多少细节是你不知道的 再理解代码 1:ViT源码阅读-PyTorch - 知乎

此芯科技加入百度飞桨硬件生态共创计划,加速端侧AI生态布局

近日,此芯科技(上海)有限公司(以下简称“此芯科技”)与百度签署硬件生态共创计划合作协议,正式加入由百度发起的硬件生态共创计划。双方将共同推动端侧AI和大模型在个人计算、车载计算以及元宇宙计算等领域…

Spring中是否可以存在两个相同ID的bean

文章目录 一、在同一个xml配置文件里配置两个相同ID的bean结论验证过程源码 二、在不同xml配置文件里配置两个相同ID的bean结论验证过程源码 三、在同一个配置类中以Bean方式添加两个名称相同的bean结论验证过程源码 四、在不同配置类中以Bean方式添加两个名称相同的bean结论验…

基础设施建设-企业级全栈测试平台的最佳实践

QECon(Quality Efficiency Conference)质量效能大会在上海正式开幕!本次大会以"数生智慧:高质量发展新引擎"为主题,深入探讨如何借助数字化和智能化技术推动软件质量的发展,为高质量经济发展提供…

华为云,让AI算力入山河

整个2023年,全球科技界都在为大模型沸腾。云计算产业作为AI大模型与产业场景间的最短路径,自然也在大模型浪潮中备受关注。目前阶段,云厂商已经纷纷入局大模型,从多个角度探索大模型带给云计算产业的可能性。 但我们往往会忽略这样…

【开发篇】八、SpringBoot整合MongoBD

文章目录 1、整合2、简单示例3、一点思考4、MongoDB的安装5、MongoDB的CRUD语法 1、整合 导入MongoBD的起步依赖:(这个starter背后是MongoDB的驱动和其他依赖,在这儿也可以看出命名的规律,redis的就是spring-boot-starter-data-r…

【数据结构-图】并查集

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

接口测试主要测试哪方面?需要哪些技能?要怎么学习?

1、什么是接口测试? 定义:测试系统组件间接口的一种测试。主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点,重点是检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑依赖关系等。 目的&#x…

选择合适的外贸公司邮箱注册服务提供商

随着全球化的发展,越来越多的企业开始涉足外贸领域。而在进行外贸业务时,邮箱是必不可少的工具之一。对于外贸公司来说,应该选择哪家邮箱服务提供商呢?口碑好安全性高的公司邮箱有Zoho Mail、阿里邮箱、腾讯邮箱、网易邮箱等。 首…

Spring cloud Sentinel介绍和安装

Sentinel介绍和安装 🌈初识Sentinel🌈安装Sentinel🌠docker 安装🌠下载sentinel镜像🌠启动sentinel镜像 🌠windows 安装🌠下载🌠运行 🌠sentinel访问 🌈微服务…

上海股票开户佣金最低是多少?怎么开万一账户!

上海股票开户佣金最低是多少?怎么开万一账户! 股票开户是指向证券公司或经纪人申请开通股票交易账户的过程。开户时需要提供个人身份信息和相关资料,完成相关的申请、签署协议以及缴纳开户费用。开户后,投资者就可以在证券市场上…

8年测试老鸟总结,Python自动化测试实现思路(细致)

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Python自动化测试…

NVM:切换node版本后无法使用npm全局包

1.新建文件夹npm_global和npm_cache 2.npm设置 npm config set prefix "C:\Users\18068\node\node_global" npm config set cache "C:\Users\18068\node\node_cache" 3.设置环境变量 新建NVM_PATH环境变量 选择缓存目录 编辑PATH环境变量 新建%NVM_PA…