基于以太坊发行ERC20 Token(代币)

2023-11-23 18:50
文章标签 token 以太 代币 发行 erc20

本文主要是介绍基于以太坊发行ERC20 Token(代币),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文将介绍基于以太坊测试链,利用Remix与MetaMask两个工具发行Token(代币),以及基于ERC20标准规范编写代币合约,供初学者参考。

ERC20 Token
也许你经常看到ERC20和代币一同出现, ERC20是以太坊定义的一个代币标准。
要求我们在实现代币的时候必须要遵守的协议,如指定代币名称、总量、实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。协议的github具体描述位于https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md。
一个标准的协议促使了代币可以在不同的应用中得到使用,如钱包和去中心化交易所。
接口定义如下:

pragma solidity ^0.4.19;contract Token {/// token总量,默认会为public变量生成一个getter函数接口,名称为totalSupply().uint256 public totalSupply;/// 获取账户_owner拥有token的数量function balanceOf(address _owner) constant returns (uint256 balance);//从消息发送者账户中往_to账户转数量为_value的tokenfunction transfer(address _to, uint256 _value) returns (bool success);//从账户_from中往账户_to转数量为_value的token,与approve方法配合使用function transferFrom(address _from, address _to, uint256 _value) returns  (bool success);//消息发送账户设置账户_spender能从发送账户中转出数量为_value的tokenfunction approve(address _spender, uint256 _value) returns (bool success);//获取账户_spender可以从账户_owner中转出token的数量function allowance(address _owner, address _spender) constant returns  (uint256 remaining);//发生转账时必须要触发的事件 event Transfer(address indexed _from, address indexed _to, uint256 _value);//当函数approve(address _spender, uint256 _value)成功执行时必须触发的事件event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

代币合约
基于ERC20编写的合约代码如下:

pragma solidity ^0.4.19;interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }contract TokenERC20 {string public name;string public symbol;uint8 public decimals = 18;  // decimals 可以有的小数点个数,最小的代币单位。18 是建议的默认值uint256 public totalSupply;// 用mapping保存每个地址对应的余额mapping (address => uint256) public balanceOf;// 存储对账号的控制mapping (address => mapping (address => uint256)) public allowance;// 事件,用来通知客户端交易发生event Transfer(address indexed from, address indexed to, uint256 value);// 事件,用来通知客户端代币被消费event Burn(address indexed from, uint256 value);/*** 初始化构造*/function TokenERC20(uint256 initialSupply, string tokenName, string tokenSymbol) public {totalSupply = initialSupply * 10 ** uint256(decimals);  // 供应的份额,份额跟最小的代币单位有关,份额 = 币数 * 10 ** decimals。balanceOf[msg.sender] = totalSupply;                // 创建者拥有所有的代币name = tokenName;                                   // 代币名称symbol = tokenSymbol;                               // 代币符号}/*** 代币交易转移的内部实现*/function _transfer(address _from, address _to, uint _value) internal {// 确保目标地址不为0x0,因为0x0地址代表销毁require(_to != 0x0);// 检查发送者余额require(balanceOf[_from] >= _value);// 确保转移为正数个require(balanceOf[_to] + _value > balanceOf[_to]);// 以下用来检查交易,uint previousBalances = balanceOf[_from] + balanceOf[_to];// Subtract from the senderbalanceOf[_from] -= _value;// Add the same to the recipientbalanceOf[_to] += _value;Transfer(_from, _to, _value);// 用assert来检查代码逻辑。assert(balanceOf[_from] + balanceOf[_to] == previousBalances);}/***  代币交易转移* 从自己(创建交易者)账号发送`_value`个代币到 `_to`账号** @param _to 接收者地址* @param _value 转移数额*/function transfer(address _to, uint256 _value) public {_transfer(msg.sender, _to, _value);}/*** 账号之间代币交易转移* @param _from 发送者地址* @param _to 接收者地址* @param _value 转移数额*/function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {require(_value <= allowance[_from][msg.sender]);     // Check allowanceallowance[_from][msg.sender] -= _value;_transfer(_from, _to, _value);return true;}/*** 设置某个地址(合约)可以创建交易者名义花费的代币数。** 允许发送者`_spender` 花费不多于 `_value` 个代币** @param _spender The address authorized to spend* @param _value the max amount they can spend*/function approve(address _spender, uint256 _value) publicreturns (bool success) {allowance[msg.sender][_spender] = _value;return true;}/*** 设置允许一个地址(合约)以我(创建交易者)的名义可最多花费的代币数。** @param _spender 被授权的地址(合约)* @param _value 最大可花费代币数* @param _extraData 发送给合约的附加数据*/function approveAndCall(address _spender, uint256 _value, bytes _extraData)publicreturns (bool success) {tokenRecipient spender = tokenRecipient(_spender);if (approve(_spender, _value)) {// 通知合约spender.receiveApproval(msg.sender, _value, this, _extraData);return true;}}/*** 销毁我(创建交易者)账户中指定个代币*/function burn(uint256 _value) public returns (bool success) {require(balanceOf[msg.sender] >= _value);   // Check if the sender has enoughbalanceOf[msg.sender] -= _value;            // Subtract from the sendertotalSupply -= _value;                      // Updates totalSupplyBurn(msg.sender, _value);return true;}/*** 销毁用户账户中指定个代币** Remove `_value` tokens from the system irreversibly on behalf of `_from`.** @param _from the address of the sender* @param _value the amount of money to burn*/function burnFrom(address _from, uint256 _value) public returns (bool success) {require(balanceOf[_from] >= _value);                // Check if the targeted balance is enoughrequire(_value <= allowance[_from][msg.sender]);    // Check allowancebalanceOf[_from] -= _value;                         // Subtract from the targeted balanceallowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowancetotalSupply -= _value;                              // Update totalSupplyBurn(_from, _value);return true;}
}

部署合约
完成代币合约编写后,可以将合约发布到Etherscan的测试链上(公链需要购买ether,而且速度较慢,建议开发在测试上进行),合约部署方式如下:

我采用Remix在线浏览器IDE才进行合约的编译和部署的,打开Remix页面样子如下:

image

点击新建按钮,将上面编辑的合约复制到IDE中:

image


复制完成后,IDE的左边会自动校验你的合约的编写是否准确,有错误会提示,警告可以忽略。

image

中间插入MetaMask讲解

MetaMask使用
由于我们是在以太坊测试链上发行合约,还是需要ether的,只不过可以免费获得,为了发行合约,我们需要测试链账户,下面我们将插入使用MetaMaskchrome插件来链接创建账户:

image


安装好后,在浏览器右上角会出现图标,点击图标,一直点击到下图,填写你的密码,进入后就创建好了一个MetaMask钱包,MetaMask会为用户创建12个英文助记词, 一定要保存好这些助记词,一定要保存好这些助记词,一定要保存好这些助记词,在其他钱包导入这个新创建的账户的时候有可能需要这些助记词。具体细节可以参考 这篇文章。

image

创建好后,会给你默认一个账号:

image


由于我们是要基于以太坊测试链发行代币,所以我们选择测试链:

image


此时,我们发现我们的账户中没有ether,依次按照如下步骤获取,

image

image


这时候会打开网页,点击图标(建议点一两次就ok,每次会给你的账户放1个ether,部署合约1个就已经搓搓有余。)。

image


一会你就会发现你们账户有金额;

image

准备工作终于做完了,现在我们开始部署代币合约,这时候点击IDE右侧横栏中的run,按照1到3确认信息,并在4中编写你要发行的代币的信息,依次是100000000,"GaoTeB","GTB"(发行总量,发行币全称,发行币简称),4步确认不误后点击create按钮发布代币合约带测试链中。

image


点击后,会弹出对话框:

image


点击submit后,如果不报错,此时,会出现你的合约信息:

image

点击合约会打开页面,你可以看到正在创建中:

image

过一会,你就会看到:

image

那么你就基本已经发行成功你的代币了!

怎么在我们的账户下看呢?

下面我们使用MetaMask工具查看,依次点击:

image


将刚才打开的页面中的信息填入MetaMask中,

image


这时候,我们就能看到啦:

image

哎,终于大功告成,下面我们来转账一回试试:

代币交易
MetaMask插件没有提供代币交易功能,同时考虑到很多人并没有以太坊钱包或是被以太坊钱包网络同步问题折磨,今天我用网页钱包来讲解代币交易。
初次进入会有一些列的确认信息,一顿点击,来到这个页面,选择与MetaMask同一个网络链(以太坊测试链):

image


然后按下图点击:

image


点击链接后,这个页面就会和你的MetaMask链接上,你会发现你的账户信息就会出现在页面上。
此时,你的Token信息并没有出现在这里,需要你认为添加:

image


点击添加,将你的Token信息填入这里:

image


此时,你会发现:

image

然后开始代币交易,我们尝试转账给别的账户,填写好信息后依次点击:

image


此时,你将会发现,你的账户的Token已经减少了。

如果你觉得这边文章对你有些帮助,请wx给作者点辛苦费吧,谢谢!

image

这篇关于基于以太坊发行ERC20 Token(代币)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/419998

相关文章

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init

【NodeJS】Unexpected token (109:0) 返回错误码500

刚开始报错是这样的: Unexpected token call 是什么我没看懂,但我发现 span.label.lable-success 后面的 #[i+1] 写错了,应该是 #{i+1} 改成完这个错误后又是一个错误提示: What? Unexpected token (109:0) 返回错误码500是什么鬼 我先将自己这段源码的 - if ... - else 检查下

解决OAuth Token,点击退出登录报404问题

首先,认证服务器发送请求 http://auth.test.com:8085/logout?redirect_uri=http://admin.test.com:8080’ 退出后报404无法跳转到网站首页,这个时候增加一个参数redirect_uri指定退出成功后跳转的路径,因为是自定义的,所以需在认证服务器做一些处理 找到源码默认实现接口DefaultLogoutPageGeneratingF

OAuth2 Token实现授权码模式

文章目录 OAuth2 授权:Resource owner password(密码模式)OAuth2 授权:Authorization code grant授权码模式,适用于浏览器模式OAuth2:Implicit(简化授权模式)OAuth:Client credentials(客户端证书)授权码模式使用案例 OAuth2 授权:Resource owner password(密

记一次knife4j文档请求异常 SyntaxError: Unexpected token ‘<‘, ... is not valid JSON

knife4j页面报错问题定位 前几天开发新接口,开发完成后想使用knife4j测试一下接口功能,突然发现访问页面报错提示:knife4j文档请求异常,但之前运行还是正常的,想想会不会与升级依赖有关系,启动其他微服务发现文档接口访问正常,排除因依赖版本升级导致在线API文档无法使用情况,还是和本服务新增接口有关系。 定位问题 首先f12打开调试台,重新刷新页面,看到console有报错提示

【Http 每日一问,访问服务端的鉴权Token放在header还是cookie更合适?】

结论先行: token静态的,不变的,放在header里面。 典型场景 ,每次访问时需要带个静态token请求服务端,向服务端表明是谁请求,此时token也可以认为是个固定的access-key。token动态的,会失效,放在cookie里面。 典型场景,业务登录态token,存在有效期的,过一段时间可能会失效。 下面具体展开下。 在选择将鉴权 Token 放在 HTTP Header 还是

JWT生成、解析token

目录 1. 导入JWT相关依赖2. JWT生成token3. JWT解析token4. 测试结果5. JWT加密、解密工具类 1. 导入JWT相关依赖 <!-- jwt认证模块--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.10.2</

python eval报错 SyntaxError: invalid token

a = eval(startTime)   File "<string>", line 1     2019-01-02 11:00:00               ^ SyntaxError: invalid token startTime = '2019-01-02 11:00:00'a = eval(startTime) 具体内容如上: 后来发现,在eval中的

OpenFeign请求拦截器,注入配置属性类(@ConfigurationProperties),添加配置文件(yml)中的token到请求头

一、需求 OpenFeign请求拦截器,注入配置属性类(@ConfigurationProperties),添加配置文件(yml)中的token到请求头 在使用Spring Boot结合OpenFeign进行微服务间调用时,需要在发起HTTP请求时添加一些默认的请求头,比如认证令牌(token)。为了实现这一功能,可以创建一个请求拦截器,并且通过@ConfigurationPropert

Unexpected token d in JSON at position 5, check bodyParser config错误解决

错误原因:json格式不对 { desc="设备1", iotProjectId=11 } 解决:通过json在线校验格式校验json格式,找出错误原因,修改 在线JSON校验格式化工具(Be JSON) 修改: {"desc": "设备","iotProjectId": 11}