solidity代币实例详解

端午节放假了，饱食终日，无所事事，用solidity写了个以太坊代币，于是离骚币诞生了，纪念屈原，今年不仅仅是读一遍离骚了。

pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
防止整数溢出问题
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}

function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}

function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}

function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}

contract StandardToken {
//使用SafeMath
using SafeMath for uint256;

//代币名称
string public name;
//代币缩写
string public symbol;
//代币小数位数(一个代币可以分为多少份)
uint8 public  decimals;
//代币总数
uint256 public totalSupply;

//交易的发起方(谁调用这个方法，谁就是交易的发起方)把_value数量的代币发送到_to账户
function transfer(address _to, uint256 _value) public returns (bool success);

//从_from账户里转出_value数量的代币到_to账户

//交易的发起方把_value数量的代币的使用权交给_spender，然后_spender才能调用transferFrom方法把我账户里的钱转给另外一个人
function approve(address _spender, uint256 _value) public returns (bool success);

//查询_spender目前还有多少_owner账户代币的使用权

//转账成功的事件
//使用权委托成功的事件
}

//设置代币控制合约的管理员
contract Owned {

modifier onlyOwner() {
require(msg.sender == owner);
_;//do something
}

//权力所有者

//合约创建的时候执行，执行合约的人是第一个owner
constructor() public {
owner = msg.sender;
}
//新的owner,初始为空地址，类似null

//更换owner成功的事件

//现任owner把所有权交给新的owner(需要新的owner调用acceptOwnership方法才会生效)
function changeOwner(address _newOwner) public onlyOwner {
require(_newOwner != owner);
newOwner = _newOwner;
}

//新的owner接受所有权,权力交替正式生效
function acceptOwnership() public{
require(msg.sender == newOwner);
emit OwnerUpdate(owner, newOwner);
owner = newOwner;
newOwner = 0x0;
}
}

//代币的控制合约
contract Controlled is Owned{

//创世vip
constructor() public {
setExclude(msg.sender,true);
}

// 控制代币是否可以交易，true代表可以(exclude里的账户不受此限制，具体实现在下面的transferAllowed里)
bool public transferEnabled = true;

// 是否启用账户锁定功能，true代表启用
bool lockFlag=true;
// 拥有特权用户，不受transferEnabled和lockFlag的限制，vip啊，bool为true代表vip有效

//设置transferEnabled值
function enableTransfer(bool _enable) public onlyOwner returns (bool success){
transferEnabled=_enable;
return true;
}

//设置lockFlag值
function disableLock(bool _enable) public onlyOwner returns (bool success){
lockFlag=_enable;
return true;
}

return true;
}

//设置vip用户
return true;
}

return true;
}
//控制合约 核心实现
require(transferEnabled,"transfer is not enabeled now!");
if(lockFlag){
}
}
_;
}

}

//端午节，代币离骚
contract LiSaoToken is StandardToken,Controlled {

//账户集合
mapping (address => uint256) public balanceOf;

constructor() public {
totalSupply = 1000000000;//10亿
name = "LiSao Token";
symbol = "LS";
decimals = 0;
balanceOf[msg.sender] = totalSupply;
}

function transfer(address _to, uint256 _value) public transferAllowed(msg.sender) returns (bool success) {
require(_value <= balanceOf[msg.sender]);

balanceOf[msg.sender] = balanceOf[msg.sender].sub(_value);
emit Transfer(msg.sender, _to, _value);
return true;
}

function transferFrom(address _from, address _to, uint256 _value) public transferAllowed(_from) returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowed[_from][msg.sender]);

balanceOf[_from] = balanceOf[_from].sub(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
emit Transfer(_from, _to, _value);
return true;
}

function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}

return allowed[_owner][_spender];
}

}


1.代码介绍

• 遵守ERC20协议
具体代码体现：contract StandardToken
ERC20协议的github地址：https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
遵守协议就是统一状态变量的名称和方法的名称，大家看代码里StandardToken合约里就是了，可能会觉得奇怪，官方文档里明明写的是像这种方法
function name() view returns (string name)
你的代码里咋没写呢？因为我定义了 string public name，而public的公共变量name，会自动生成一个返回name的name()的方法，所以我不用重复写function name()了，其它几个变量也是一样的
• 引入SafeMath，防止整数溢出漏洞(SMT，BEC)
具体代码实现：library SafeMath
官方介绍地址：https://ethereumdev.io/safemath-protect-overflows/
• 设置一个控制合约
具体代码体现：contract Controlled
作用：
1.有突发情况，可以暂停所有人的转账
2.设置黑名单功能，可以冻结黑名单帐户，让它无法转账
3.也可以设置vip帐户，不受前面两个的控制
• 管理员
具体代码体现：contract Owned
既然有控制合约，各种转账控制，那么谁来设置这个东西，如果人人都有权限，那就乱套了，所以需要一个唯一管理员；管理员也可以把这个权力禅让给一个新的管理员
• 具体实现代币功能
具体代码体现：contract LiSaoToken
功能点，通俗的讲就是 :
1.自己转账给他人(transfer)
2.自己帮别人转账给另外一个人(transferFrom)
3.我委托你帮我管理我的代币，使用权给你,但是币还在我这(approve)
4.查看一下我还有多少币委托你在管理(allowance)

2.开发部署

• remix，开发和部署一体的
solidity的开发工具，在线工具：http://remix.ethereum.org，浏览器直接打开就行，很省事，当然也可以安装本地版，remix官网的安装介绍看起来很简单，几行命令就ok了，但是实际上很坑，反正我放弃了
• 发布流程

设置gas价格，确认交易

然后就可以看的remix的日志信息了

点开连接等待挖矿完成就好了