目录
1.以太坊简介
1.什么是以太坊
2.以太坊虚拟机(EVM)
3.以太坊工作流程
4.交易和消息
2.智能合约
1.以太坊geth客户端基本操作
2.智能合约例子
3.智能合约的JSON-RPC接口
4.以太坊windows钱包mist 智能合约
附录
附录1
附录2
1.以太坊简介
1.什么是以太坊
以太坊是一个能够在区块链上实现智能合约、开源的底层系统。换言之,以太坊是可编程的区块链,它并不是给用户一系列预先设定好的操作(例如比特币交易),而是允许用户按照自己的意愿创建复杂的操作。这样一来,以太坊是就可以作为多种类型去中心化区块链应用的平台,这些应用比如包括之前很火的各种代币但并不仅限于此,我们可以做很多除了代币之外的东西,比如你可以输出一行代表自己不是外行身份的hello world,或者在上面做一个简单的计算器,总之你可以在上面实现你想要的任何功能。
2.以太坊虚拟机(EVM)
以太坊狭义上是指一系列定义去中心化应用平台的协议,它的核心是以太坊虚拟机,可以执行任意复杂算法的编码。在计算机科学术语中,以太坊是“图灵完备的”,所谓图灵完备就是指可以实现和执行所有可被描述的计算。开发者可以使用编程语言创建出在以太坊模拟机上运行的应用,现在使用最多最流行的语言是solidity,在后面会描述怎么使用solidity进行智能合约的编写。和其他区块链一样,以太坊也有一个点对点网络协议。以太坊区块链数据库由众多连接到网络的节点来维护和更新,每个网络节点都运行着以太坊虚拟机并执行相同的指令。这个过程使得在以太坊上的运算比在传统“电脑”上慢和昂贵。然而,每个以太坊节点都运行着以太坊虚拟机是为了保持整个区块链的一致性。去中心化的一致性使以太坊有极高的故障容错性,保证零停机,而且可以使存储在区块链上的数据保持永远不变且抗审查。
3.以太坊工作流程
以太坊合并了很多对比特币用户来说十分熟悉的特征和技术,同时自己也进行了很多修正和创新。比特币的区块链纯粹是一个关于交易的列表,而以太坊的基础单元是账户。以太坊区块链跟踪每个账户的状态,所有以太坊区块链上的状态转换都是账户之间价值和信息的转移。以太坊用户分为两类:外部账户和合约账户。外部账户就是在以太坊上申请的用户个人账户,由私人密码控制;合约账户则是由它们的合约编码控制。“智能合约”这个流行的术语指的是在合约账户中编码——交易被发送给该账户时所运行的程序
智能合约是一个在以太坊系统里的自动代理人,前面说道它有一个自己的以太币地址,当用户向合约的地址里发送一笔交易后,该合约就被激活,然后根据交易中的额外信息,合约会运行自身的代码,最后返回一个结果,这个结果可能是从合约的地址发出另外一笔交易。需要指出的是,以太坊中的交易,不单只是发送以太币而已,它还可以嵌入相当多的额外信息。如果一笔交易是发送给合约的,那么这些信息就非常重要,因为合约将根据这些信息来完成自身的业务逻辑。只有当外部账户发出指令时,合约账户才会执行相应的操作。所以合约账户不可能自发地执行诸如任意数码生成或应用程序界面调用等操作,只有受外部账户提示时,它才会做这些事。智能合约可以简单的理解为一段可执行的程序片段,具体的代码由发布人使用特定的编程语言来编写,在本地编译成功后可以发布到区块链上。而以太坊的智能合约也可以理解为一个特殊的交易(包括可执行代码的),被发送出去后会被矿工打包记录在某一个区块中,当需要调用这个智能合约的方法时只需要向这个智能合约的地址发送一笔交易即可,通过交易触发智能合约后智能合约的代码就会在EVM中执行了。
和比特币以及ripple一样,以太坊用户必须向网络支付少量交易费用,这个称为gas,这可以使以太坊区块链免受无关紧要或恶意的运算任务干扰 。交易的发送者必须在激活的“程序”每一步付款,包括运算和记忆储存。费用通过以太坊自有的有价代币,以太币的形式支付。交易费用由节点收集,节点使网络生效,矿工就是以太坊网络中收集、传播、确认和执行交易的节点。矿工们将交易分组——包括许多以太坊区块链中账户“状态”的更新——分成的组被称为“区块”,矿工们会互相竞争,以使他们的区块可以添加到下一个区块链上。矿工们每挖到一个成功的区块就会得到以太币奖励。这就为矿工们带来了经济激励,促使矿工为以太坊网络贡献硬件和电力。以太坊挖矿机制这一点和其他区块链机制比起来区别不大。前面提到了由以太坊网络上的交易而产生的每一次计算,都会产生费用,这个费用是以称之为”gas”的来支付。gas就是用来衡量在一个具体计算中要求的费用单位。gas price是你愿意在每个gas上花费Ether的数量,以“gwei”进行衡量。“Wei”是Ether的最小单位,1Ether表示10^18Wei. 1gwei是1,000,000,000 Wei。对每个交易,发送者设置gas limit和gas price。gas limit和gas price就代表着发送者愿意为执行交易支付的Wei的最大值。用户愿意支付的费用越多,交易就可能被越快进行处理,这些费用最后都发送给了矿工的地址。
4.交易和消息
以太坊是一个基于交易的状态机。换句话说,在两个不同账户之间发生的交易才让以太坊全球状态从一个状态转换成另一个状态。一个交易就是被外部拥有账户生成的加密签名的一段指令,序列化,然后提交给区块链。
"交易"这个术语在以太坊里被用来指代一个用来存储消息的被签名数据包在区块链上从一个外部拥有账户发送至另一个账户的过程。交易包括:
这个消息的接收者
一个签名,用来证明发送者有意向通过区块链向接收者发送消息
价值域 - 从发送方转移到接受方的wei (ether/10^18) 的数量
一个可选的数据域,用来储存发送给合约的消息
一个GASLIMIT值,代表了这个交易的执行最多被允许使用的计算步骤
一个GASPRICE值,代表了交易发送者愿意支付的gas费用。一个单位的gas表示了执行一个基本指令,例如一个计算步骤。
合约具有发送"消息"到其他合约的能力。消息是一个永不串行且只在以太坊执行环境中存在的虚拟对象。他们可以被理解为函数调用(function calls)。
一个消息包括:
明确的消息发送者
消息的接收者
一个可选的数据域,这是合约实际上的输入数据
一个GASLIMIT值,用来限制这个消息出发的代码执行可用的最大gas数量
总的来说,一个消息就像是一个交易,除了它不是由外部账户生成,而是合约账户生成。当合约正在执行的代码中运行了CALL 或者DELEGATECALL这两个命令时,就会生成一个消息。消息有的时候也被称为"内部交易"。与一个交易类似,一个消息会引导接收的账户运行它的代码。因此,合约账户可以与其他合约账户发生关系,这点和外部账户一样。
上面这些参数在后面的智能合约详细介绍的时候,会有更加清楚的介绍。交易—消息通信和合约创建交易两者都总是被外部拥有账户触发并提交到区块链的,交易是外部世界和以太坊内部状态的桥梁。
2.智能合约
1.以太坊geth客户端基本操作
以太坊有多种客户端,目前使用最多的是geth客户端,Linux下的部署过程为:
1.git clone https://github.com/ethereum/go-ethereum
- wget -c https://storage.googleapis.com/golang/go1.10.1.linux-amd64.tar.gz(解压安装go语言环境)
3.cd go-ethereum
4.make geth
Installing from PPA:
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum
ERR: sudo命令
vi /etc/sudoers
找到
#Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
在他下面添加xxx ALL=(ALL) ALL (这里的xxx是你的用户名)
添加下面:
youuser ALL=(ALL) ALL
ERR: sudo: unable to resolve iZwz9b612cyspv62gllm18Z
$ vim /etc/hostname
iZ2zecsdy8flu603bmdg1bZ
$ vim /etc/hosts
127.0.0.1 localhost iZ2zecsdy8flu603bmdg1bZ
结尾处增加hostname。
ERR:节点间同步报错:retrieved hash chain is invalid
date命令查看系统时间是否一致。不一致调整系统时间
公司192.168.10.249环境已经部署好了以太坊的私链,可以在上面进行测试。
以下是创建创世块的操作:新建文件夹,命名随意,在此文件夹下创建genesis.json文件和data文件夹,genesis.json的内容配置如下:
{
"config": {
"chainId": 123456,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"nonce": "0x0000000000000042",
"difficulty": "0x020000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x4c4b40",
"alloc": {}
}
如果需要预设以太币,alloc节点设置:
"alloc":
{
"0xf883bd04cbedccf02544c973b8b8f21fd2c5d6da":
{
"balance":"15000000000000000000000000"
}
}
账户需要在
在命令行下进入刚才创建的文件夹,输入如下命令:
geth --datadir data init genesis.json
init 表示初始化区块,后面跟着创世块的配置文件genesis.json,datadir 数据存放的位置。然后创世块的设置就好了。
接下来是启动节点的操作:geth --datadir data --networkid 123456 --rpc --rpccorsdomain "*" --nodiscover console --rpcaddr 192.168.10.249,各个参数的意义可以执行geth -h查看。执行成功后将进入区块链的JavaScript控制台环境,下图是成功进入控制台的截图:
下面是一些基本的geth操作:
创建新账号
personal.newAccount()
或者 personal.newAccount("123456")
查看节点信息
admin.nodeInfo
挖矿
开始挖矿 miner.start(1)
停止挖矿 miner.stop()
查看当前矿工账号
eth.coinbase 默认为第一个账户
修改矿工账号
miner.setEtherbase(eth.accounts1)
查看账户信息
eth.accounts0
查看账户余额
eth.getBalance(eth.accounts0)
或者 web3.fromWei(eth.getBalance(eth.accounts0), "ether")
解锁账号
personal.unlockAccount(eth.accounts0)
使用账户资金前都需要先解锁账号
2.智能合约例子
学会了这些基本的命令,我们来进行合约的测试:
第一步
首先创建两个账户,并且设置密码。
personal.newAccount("123456")
personal.newAccount("123456")
第二步
确认新用户的账户余额为0, 并开始"挖矿"
eth.getBalance(eth.accounts0)
miner.start()
最后使用miner.stop()停止挖矿,查看余额可以看到我们已经得到了20个以太币(不要奇怪为什么那么多0,见附录2的以太币计量单位描述)。
第三步
智能合约的编写,我们使用solidity语言进行合约的编写,solidity语言的特性和使用方法可以参考官方文档:http://solidity.readthedocs.io/en/develop/,它很简单,只要使用过高级语言编程,可以很快入门。智能合约可以在命令行进行编译,但是选择在线编译可能更好,首先是简单易操作,二者更加直观的可以看到编译出来的二进制等等信息。在线编译的地址为:https://ethereum.github.io/browser-solidity。我们编写一个简单代币的合约进行测试,拷贝到代码输入框内(测试代码见附录),如图:
左边为代码框,点击右边的detail按钮,可以看到编译得到的结果。拷贝得到WEB3DEPLOY属性内编译出来的代码:
var browser_ballot_sol_tokenContract = web3.eth.contract([{"constant":false,"inputs":{"name":"account","type":"address"},{"name":"amount","type":"uint256"},"name":"issue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":{"name":"to","type":"address"},{"name":"amount","type":"uint256"},"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":{"name":"account","type":"address"},"name":"getBalance","outputs":{"name":"","type":"uint256"},"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":{"indexed":false,"name":"account","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},"name":"Issue","type":"event"},{"anonymous":false,"inputs":{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},"name":"Transfer","type":"event"}]);
var browser_ballot_sol_token = browser_ballot_sol_tokenContract.new(
{
from: web3.eth.accounts0,
data: '0x6060604052341561000f57600080fd5b336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506103d78061005e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063867904b41461005c578063a9059cbb1461009e578063f8b2cb4f146100e0575b600080fd5b341561006757600080fd5b61009c600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061012d565b005b34156100a957600080fd5b6100de600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101d9565b005b34156100eb57600080fd5b610117600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610362565b6040518082815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561018857600080fd5b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561022557600080fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509190505600a165627a7a72305820523cf3c14817b40feb1b74eb98f98f5dcd82a8b728d96989159119d606663a550029',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' contract.address ' transactionHash: ' contract.transactionHash);
}
})
将上面粗体字部分的变量修改为token,这是为了方便使用合约的时候使用简单的名称,而不至于太长。
第四步
将账户解锁,部署合约必须要解锁账户
personal.unlockAccount(eth.accounts0,"123456",99999999)
第一个参数是账户,第二个参数是密码,第三个是解锁账户时间,单位为秒,设置长一点,默认是5分钟
第五步
部署合约,将第三步得到的修改过的编译代码拷贝到命令行
绿色的contract是得到的合约地址,将其记下来。接下来需要提交的操作都需要挖矿操作进行确认。执行miner.start()进行合约部署的确认。
可以看到合约已经被确认,地址已经写入了区块链。
第六步
测试合约,代码实现了一个简单的Token合约功能。issue 函数可以向充值以太到合约账户transfer 函数可以向其他账号发送token,getBalance 函数可以获取某个账号的token余额。
充值
token.issue.sendTransaction(eth.accounts0, 100, {from: eth.accounts0})
miner.start(1)
miner.stop()
发送token
token.transfer(eth.accounts1, 30, {from: eth.accounts0})
miner.start(1)
miner.stop()
余额查询
token.getBalance(eth.accounts0)
token.getBalance(eth.accounts1)
可以看到账户1先充值了100,然后往账户2转账了30,结果是账户1余额为70,账户2余额为30。
3.智能合约的JSON-RPC接口
合约的交互都是一次交易,而我们要做的就是把要调用的方法和参数按照api规定的以参数的形式向区块请求一次交易,以太坊接收到我们的请求后通过解析传递的参数来执行相关的合约代码。我们使用以下两个RPC接口测试:eth_sendTransaction和eth_call。其他的RPC接口可以参见https://github.com/ethereum/wiki/wiki/JSON-RPC。
首先说一下eth_sendTransaction和eth_call的参数意义:
eth_sendTransaction
from: 发送交易的外部账户地址.
to: 接受地址,我们的例子为合约地址.
gas: 可选项,gas个数.
gasPrice: 可选项,gas价格
value: 可选项,需要发送的以太币个数,合约调用不需要
data: Data的属性的值具体可以看官方文档Contract ABI的介绍。这里大概说下:data的值相对来说不是固定的,具体怎么生成与合约的参数类型,参数数量都有关联,https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI。
nonce: 交易号,建议值设置为上一次发送交易值 1.
例:
params: [{
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0", // 30400
"gasPrice": "0x9184e72a000", // 10000000000000
"value": "0x9184e72a", // 2441406250
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
}]
上面我们提到的data,在我们的token例子中,data的值如下:
充值issue (address account, uint amount)
这个方法有俩个参数,address充值账号,uint充值数量。根据Contract ABI,data值应该为方法名的sha3的前8个字节 参数的64字节,不够前面补充为0。这里方法名并不是issue (address account, uint amount)而是issue(address,uint256)的sha3值。在线编译的时候,我们点击右边的detail按钮,可以看到编译得到的结果。拷贝得到WEB3DEPLOY属性内编译出来的代码,现在我们可以在FUNCTIONHASHES属性中得到各个函数的sha3值:
我们的data第一部分为issue函数的sha3值: 0x867904b4000000000000000000000000,第二部分为第一个参数account值613414d7b8a09504a73a839afbe1a0f4d85b7fdc,第三部分为第二个参数amount值:000000000000000000000000000000000000000000000000000000000000000a(采用的是16禁止,因此十进制值为10)。于是我们这段data表示的含义就是:调用issue函数,往613414d7b8a09504a73a839afbe1a0f4d85b7fdc地址内转账,转账金额为10。得到data值为:
0x867904b4000000000000000000000000613414d7b8a09504a73a839afbe1a0f4d85b7fdc000000000000000000000000000000000000000000000000000000000000000a
那么最后我们调用eth_sendTransaction方法传递参数JSON对象为:
{
"jsonrpc": "2.0",
"method": "eth_sendTransaction",
"params": [
{
"from": "0x613414d7b8a09504a73a839afbe1a0f4d85b7fdc",
"to": "0xcea8a381d6b3fdb94d97274557342b5e9302ab03",
"data": "0x867904b4000000000000000000000000613414d7b8a09504a73a839afbe1a0f4d85b7fdc000000000000000000000000000000000000000000000000000000000000000a"
}
],
"id": 1
}
一些非可选项的参数没有设置,比如gas值等。返回:此交易的hash值,矿工通过挖矿确认后,交易就生效了。
返回的json串中的result节点值就是这条交易的哈希值。
测试合约的transfer方法和issue的方法一样,只要把data的值按照规范设置正确的编码就好了。
eth_call
发送交易类型的消息需要使用eth_sendTransaction接口,查询类的合约方法则使用eth_call接口。eth_call接口的意思是立即执行一个消息调用,而不会在块链上创建事务。eth_call的参数和eth_sendTransaction接口参数一样,唯一不同的是没有nonce参数,因为他不是发送交易到以太坊,不需要nonce。
getBalance(address account)方法的data编码第一部分为getBalance函数的sha3值:0xf8b2cb4f000000000000000000000000,第二部分为account的值:613414d7b8a09504a73a839afbe1a0f4d85b7fdc。
得到data值:
0xf8b2cb4f000000000000000000000000613414d7b8a09504a73a839afbe1a0f4d85b7fdc
注意,这个方法需要俩参数,处理一个JSONobject外,还有一个字符串参数,这俩可以为“”或者”latest”, “earliest” or “pending”,那么最后我们调用eth_call方法传递参数JSON对象为:
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0x613414d7b8a09504a73a839afbe1a0f4d85b7fdc",
"to": "0xcea8a381d6b3fdb94d97274557342b5e9302ab03",
"data": "0xf8b2cb4f000000000000000000000000613414d7b8a09504a73a839afbe1a0f4d85b7fdc"
},
"latest"
],
"id": 1
}
一些非可选项的参数没有设置,比如gas值等。返回:得到的余额值
16进制的0x50,表示该账户余额为80。
4.以太坊windows钱包mist 智能合约
安装环境
安装Ethereum-Wallet,安装地址和配置以具体需求为准
(1)钱包镜像下载地址(https://github.com/ethereum/mist/releases)
(2)在F盘新建文件夹Eth,专门放置以太坊开发环境
(3)把下载的压缩包解压到F:Eth 目录下
安装geth
(1)下载地址https://ethereum.github.io/go-ethereum/downloads/
(2)安装geth到F:Eth 目录下
私有链搭建
(1)在F:Eth 目录下创建创世块文件genesis.json,文件内容如下:
{
"nonce": "0x0000000000000042",
"difficulty": "0x40000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0xffffffff",
"alloc": {
"3282791d6fd713f1e94f4bfd565eaa78b3a0599d": {
"balance": "1337000000000000000000"
},
"17961d633bcf20a7b029a7d94b7df4da2ec5427f": {
"balance": "229427000000000000000"
}
},
"config": {
"chainId": 15,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
}
}
(2)打开cmd,进入F:Eth 目录下,创世块文件初始化:geth -datadir "�%chain" init genesis.json
(3)打开geth控制台:geth -datadir "�%chain" console
(4)创建两个新账户,用来启动私有链的挖矿,windows下的geth命令和linux下几乎一致,不再赘述。
(5) 输入exit,退出控制台
(6)启动私有链节
geth -rpc -rpcaddr "192.168.10.172" -networkid 123456 -nodiscover -maxpeers 5 -datadir "�%chain" -rpccorsdomain "*" console
targetgaslimit –每个块的gas上限,这里可以暂时理解为容量 rpc –启动rpc通信,可以进行智能合约的部署和调试 rpcaddr –rpc接口的地址 rpcport –rpc接口的端口号 port –网络监听端口,用于节点之间通信 rpcapi –设置rpc的范围,暂时开启eth,web3,personal足够 networkid –设置当前区块链的网络ID,是一个数字,可以随便写 identity –区块链的标示,随便填写,用于标示目前网络的名字 nodiscover 禁止被网络中其它节点发现,需要手动添加该节点到网络 maxpeers 最大节点数量 datadir –设置当前区块链网络数据存放的位置 ,rpccorsdomain 限制rpc访问源的ip,console –启动命令行模式,可以在Geth中执行命令*。192.168.10.172改为自己的IP。
(7)进入F:Ethwin-unpacked ,运行Ethereum Wallet.exe
(8)挖矿
在控制台输入miner.start(1),可以开始挖矿,在钱包可以看到以太币数量的变化,可以一直执行挖矿操作,这样后面调用合约的时候就不用每次执行一次操作就来执行一次挖矿确认命令。
部署智能合约
(1)在主页面点击CONTRACTS
(2)点击DEPLOY NEW CONTRACT,部署合约
选择智能合约发起账户,这里选择Main account, 合约以太币数量填0
(3)编写的智能合约代码,将附录的代码粘贴到编辑框
在右边选择Token。
(4) 点击DEPLOY
上面可以选择费用,选择费用越高,被确认时间就可能越短。
输入账户密码确认,然后完成部署 ,等到矿工挖矿确认。
当智能合约得到区块确认,说明智能合约被保存到区块中,部署智能合约成功。
调用智能合约
(1)回到主页面,点击CONTRACTS
(2) 点击进入刚才部署的智能合约
可以看到合约的三个函数
调用Issue和Transfer以及GetBalance进行合约的测试。
发布资产
查看余额
转账操作
转账后账户的余额
附录
附录1
token测试合约代码:
contract Token {
address issuer;
mapping (address => uint) balances;
event Issue(address account, uint amount);
event Transfer(address from, address to, uint amount);
function Token() {
issuer = msg.sender;
}
function issue(address account, uint amount) {
if (msg.sender != issuer) return;
balancesaccount = amount;
}
function transfer(address to, uint amount) {
if (balancesmsg.sender < amount) return;
balancesmsg.sender -= amount;
balancesto = amount;
Transfer(msg.sender, to, amount);
}
function getBalance(address account) constant returns (uint) {
return balancesaccount;
}
}
附录2
以太坊中代币数量的计量单位说明
Unit | Wei Value | Wei |
---|---|---|
Wei | 1 | 1wei |
Kwei (babbage) | 1e3 wei | 1,000 |
Mwei (lovelace) | 1e6 wei | 1,000,000 |
Gwei (shannon) | 1e9 wei | 1,000,000,000 |
microether (szabo) | 1e12 wei | 1,000,000,000,000 |
milliether (finney) | 1e15 wei | 1,000,000,000,000,000 |
ether | 1e18 wei | 1,000,000,000,000,000,000 |