使用 在线环境
编写第一个智能合约
在这个合约代码里面,我们定义了一个名为 “Hello” 的合约。在合约初始化时,保存了一个字符串。例如,传入 “hello world”,每次调用 say() 函数时将返回该字符串
1 | pragma solidity ^0.4.20; |
选择这个版本是 0.4.21+commit,有些是不成功的
点击那个 Details,来到 WEB3DEPLOY
把第一行的 var_greeting = /* var of type string her e*/;
改成 var_greeting = "hello world";
第 6 行的 from: web3.eth.account[0]
改为 from: web3.eth.account[2]
修改部署账户
1 | var _greeting = "hello world"; |
先看一下现在的账户
将上面这一段复制到 geth 的控制台(先开始挖矿 ⛏)
如果提示这样,是因为 u2 没有解锁账户
解锁personal.unlockAccount(u2,'123456')
部署成功
看一下,u2 的账户余额变少了,部署合约用掉了
运行合约,调用 hello.say(),可以看到输出了 hello world
ERC-20 Token 合约
什么是 Token
以太坊的一个重要的应用就是融资。融资的过程,和股票操作类似,合约的创建者就是上市公司,账户余额就是持有的股份。账户余额表示一个由合约创建者定义的值,Token 就是余额的单位(也可以理解为一种凭证)
Token 合约
在之前,我们使用账户地址进行转账之类的操作,在引入智能合约以后,从本质上看,Token 合约是指包含对账户地址及其余额的映射的智能合约
比如一开始有这样之一张表,他就是账户与余额之间的映射
账户地址(Holder Address) | 余额(Balance) |
---|---|
0x0000…0000 | 0 |
0x32rd….w3ed | 100 |
0x2ejs….we3c | 100 |
Total Supply | 200 |
当 Token 被从一个账户转移到另一个账户的时候
比如一笔从 0x32rd….w3ed 转 10 个 Token 到 0x2ejs….we3c 的时候,将发生这样的变化
账户地址(Holder Address) | 余额(Balance) |
---|---|
0x0000…0000 | 0 |
0x32rd….w3ed | 90 |
0x2ejs….we3c | 110 |
Total Supply | 200 |
如果该 Token 允许,我们可以更改 Token 的总供给
可以通过构造新的 Token 来增加,构造 50 个 Token 并放到 0x2ejs….we3c 中,将导致如下变化:
账户地址(Holder Address) | 余额(Balance) |
---|---|
0x0000…0000 | 0 |
0x32rd….w3ed | 90 |
0x2ejs….we3c | 160 |
Total Supply | 250 |
也可以减少 Token 的总供给,可以通过销毁现有的 Token 来减少,在地址 0x2ejs….we3c 中销毁 10 个 Token 将导致如下变化:
账户地址(Holder Address) | 余额(Balance) |
---|---|
0x0000…0000 | 0 |
0x32rd….w3ed | 90 |
0x2ejs….we3c | 150 |
Total Supply | 240 |
另一种销毁的方式是往一个未创建私钥的地址发送 Token,通常是 0 地址,但这种方法不会减少 Token 的总数
账户地址(Holder Address) | 余额(Balance) |
---|---|
0x0000…0000 | 40 |
0x32rd….w3ed | 90 |
0x2ejs….we3c | 110 |
Total Supply | 240 |
ETC-20 Token 合约
可以简单的理解为以太坊上的一个代币协议,所有基于以太坊开发的代币都要遵循此协议。遵守协议的代币是标准化的代币,可以得到各种以太坊钱包的支持,用在不同的平台和项目中
ERC-20 标准接口
name():返回 ERC-20 代币的名字(string 类型)例如:”my_Token”
function name() constant returns (string name)
symbol():返回代币的简称,例如:”TNT”,简称通常三四个字母
function symbol() constant returns (string symbol)
decimals():返回 Token 使用的小数位数,例如设置为 3,表示支持三位小数
function decimals() constant returns (uint8 decimals)
补充:确定要取的小数位数时,应遵循如下原则:
- Token 合约表示的是一个不可切分的物体嘛?如果是,就将小数设置为 0
- Token 合约表示的是一个有特定小数位数的物体吗?如果是就将小数设置为那个数字
- 如果上述两者都不是,将小数位数设置为 18
被创建的 Token 的数量,应该等于全部 Token 的数量(要求是 10 的倍数)
totalSupply():返回 Token 的总供给量
function totalSupply() constant returns (uint totalSupply)
balanceOf():返回某个账户地址余额,给个地址就可以查到余额,所有数据在区块链上是公开的
function balanceOf(address _owner) constant returns (uint balance)
transfer():从代币合约的调用者地址上转移 _value 数量的 Token 到地址 _to,且必须触发 transfer 事件
function transfer(address _to, uint _value) returns (bool success)
当使用 Token 对智能合约中的一个函数进行支付的时候他就不起作用了。因为智能合约运行的时候,他没有办法获得“从那个地址转账到哪里”的细节,也就无法保证合约用户已经支付了启动合约的资金
想象一下,有一个 hello 合约被部署在网络上,该合约有一个函数 sayHello(),该函数要 10 个 Token 才能运行起来,账户 A 已经有 20 个 Token,他希望调用这个函数,他该怎么把足够的 Token 支付给 Hello 合约呐?
这时就需要下面这里俩了:
transferFrom():从地址 _from 发送数量为 _value 的 Token 到地址 _to,且必须触发 transfer 事件。该方法用于允许合约代理某人转移 Token,条件是 from 账户必须是经过 approve()
function transferFrom(address _from,address _to,uint _value) returns (bool success)
approve():允许 _spender 多次取回账户余额,最高金额设置为 value,如果此次调用此函数,将以 _value 覆盖当前金额
function approve(address _spender,uint _value) returns (bool success)
当持有者向一个地址(常常是智能合约)转移最大特定数量的 Token,也就是所谓的 “配额”时,Token 持有者使用 approve() 来提供这些信息
下面这个表括号里的内容是我加上的方便称呼
账户地址(Holder Address) | 配额地址(Allowence Address) | 配额(Allowence) |
---|---|---|
0x1234….(A) | 0xabcd….(X) | 25 |
0x1234….(A) | 0xdcba….(Y) | 15 |
0x4321….(B) | 0xabcd….(X) | 200 |
0x4321….(B) | 0xdcba….(Y) | 5 |
A 可以向 Y 合约转移 15 个 Token,即配额为 15 个 Token
B 可以向 Y 合约转移 5 个 Token,即配额为 5 个 Token
一旦一个许可被创建,合约就可以在一个账户的配额中占用许可数量的 Token,作为合约的一部分运行,账户 A 可以调用 sayHello(),而 sayHello() 可以使用 transferFrom() 从账户 A 的余额中获得 10 个 Token 并开始他的工作,如果余额不足 10 或配额不足 10,sayHello() 就会停止运行。所以 B 就不能调用,以为 B 配额为 5
allowance():返回 _spender 仍然被允许从 _owner 提取的金额,函数用于指定从一个给定地址转移到另一个给定地址的 Token 数量
function allowance(address _owner,address _spender) constant returns (uint remaining)
配额可以超过一个地址的余额,所以使用 allowance() 函数的时候要考虑用户余额问题
transfer() 和 approval 属于事件(Event)是为了方便获取日志提供的
前者在代币被转移时触发,用于描述 Token 从一个地址转移到另一个地址的细节
后者在调用 approve() 方法时触发,用于描述 Token 被允许从一个地址转移到另一个地址的细节
他们都可以用于跟踪地址余额和配额的变化,无需查询区块链
在 Token 构造时,会发出一个带有 0 地址的 transfer 事件作为源
被销毁时没有事件发出,ERC-20 Token 合约通过 transfer() 将 Token 发送到 0 地址来代替真正的“销毁”Token