区块链智能合约编程二:简单代币的实现

标签: 以太坊  代币  区块链  智能合约

本文介绍如何以solidity语言来实现简单的代币。

工具:remix编译器。如果不熟悉remix的可以到我第一章博客学习https://blog.csdn.net/qq_42247900/article/details/81529674

何为代币?故名思意:代替货币的意思,古代以金银为一般等价物拥有了货币的属性。到了宋朝,出现了银票,有政府公信力背书,一张纸成为了一般等价物。到了现代,支付宝、微信的出现,让人们进入了无现金的数字货币时代。由此可见,数字货币将是未来的趋势所在。我们实现的代币就是以太坊中的数字货币。

首先,我们要理解代币拥有哪些功能?

1:总发行量。就像央行发行人民币一样需要一个发行量,在代码中用totalSupply表示。

2:交易功能。作为一种数字货币,交易功能必不可少的。在以太坊中,交易就是一个地址的代币持有量转移到另一个地址中。

3:记账功能。作为一种数字货币,为每个用户记账的功能也必不可少。在以太坊中,习惯性地称为balanceof(余额)。

第一步:打开remix创建simpleToken.sol文件,选择solidity语言版本并定义一个simpletoken合约:

pragma solidity ^0.4.7;

contract simpletoken{
    
}

 

 

第二步:实现记账功能。请看下面账单:

姓名 余额
张三 100
李四 200
......... .........

观察账单,我们会发现每个人之间都有与之对应的余额。在计算机编程中,我们通常称这种存储结构为键值对存储。那么在solidity语言中也实现这种存储结构,这种类型叫做映射类型——mapping(类型1=>类型2)

所以我们可以用mapping(address=>uint256) balanceof来表示账户地余额。

简单解释下address地址类型,在以太坊中,无论是账号还是合约,都用地址来表示。如0xca35b7d915458ef540ade6068dfe2f44e8fa733c,就是一个账号地址。智能合约部署到以太坊中,系统也相应地给出一个地址值。

uint256:256位长度无符号的整形,什么叫无符号?就是没有正负符号的整数。

 

第三步:实现总发行量。

实现总发行量,简单来说就是让一个代币管理者拥有最先发行的代币数量,然后由代币管理者转移到其他投资者手中。

所以我们首先需要实现一个构造函数,然后把总发行量放到管理者手中。

constructor(uint256 totalSupply){
        balanceof[msg.sender]=totalSupply;
    }

这里解释下msg.sender,在以太坊中,把智能合约部署到节点的账号记录为msg.sender,也就是说部署智能合约的账号地址就成为了代币的管理者——owner。

 

第四步:实现转账功能

前文已经把发行总量交到代币管理者手中了,那么现在就是要把管理者手中的代币交易到其他投资者账户中。

所谓的交易,就是把卖家的余额做减法运算,买家的余额做加法运算。

我们定义一个公有的交易函数。参数是目标地址address to和交易额uint256 value。

 function transfer(address to,uint256 value) public{

        //管理者手中代币减少
        balanceof[msg.sender] -=value;
        //投资者手中代币增加
        balanceof[_to] +=value;

}

这样一来我们简单的代币功能基本实现了,但不要以为这样就很完美了。下面我部署下代码展示下会出现的问题。

首先在complie菜单栏点击 Start Compile 按钮开始编译,然后在run菜单栏点击Deploy开始部署。

 

下面开始转账。

管理者账户 0xca35b7d915458ef540ade6068dfe2f44e8fa733c

投资者账户(可以随便填,但位数要和账户管理者保持一致,否则报错,这里我在管理者账户后面改了一个字符) 0xca35b7d915458ef540ade6068dfe2f44e8fa733d

 

转账完毕后查询投资者账户是多了50个代币,现在查看下管理者账户是否减少了50.

 

确实减少了50,这是正常的交易,我们的实现的没问题,那现在搞点非正常的交易。

 

此时发现即使交易额大于管理者余额,交易还是可以进行的,而且投资者账户没有异常。聪明的小伙伴们就已经知道管理者的余额肯定有问题,那么现在查看下管理者的余额:

按照常识理解,管理者的资产应该变为-50才对,但这个数变为相当庞大。这是因为uint这个变量的问题(无符号整形,相比int而言没有负数之说)。规则如下:记uint最大值为max,当uint值为0,0-1=max,当uint值为max,max+1=0。

所以我们要在转账之前做下校验,在solidity中,提供了方便校验地函数require()

 //校验管理者的余额是否足够
        require(balanceof[msg.sender]>=value);

下面我们来部署下看看效果:

 

投资者账户0xca35b7d915458ef540ade6068dfe2f44e8fa733d余额没变,正常交易被回滚说明校验是成功的。那么还有什么问题会发生呢?qin请看下面的非正常交易:

我们向投资者账户转入超过uint256最大值:115792089237316195423570985008687907853269984665640564039457584007913129639935的数,在此基础+10,也就是转115792089237316195423570985008687907853269984665640564039457584007913129639945个代币

所以,还需要做下防溢出校验

 //防溢出校验
        require(balanceof[to]+value>=balanceof[to]);

最终代码如下:

pragma solidity ^0.4.7;

contract simpletoken{
    mapping(address=>uint256) public balanceof;
    
    constructor(uint256 totalSupply){
        balanceof[msg.sender]=totalSupply;
    }
    
      function transfer(address to,uint256 value) public{
        //校验管理者的余额是否足够
		require(balanceof[msg.sender]>=value);
        //防溢出校验
		require(balanceof[to]+value>=balanceof[to]);
        //管理者手中代币减少
		balanceof[msg.sender] -=value;
		//投资者手中代币增加
        balanceof[to] +=value;
    }
}

 

原文链接:加载失败,请重新获取