以太坊智能合约开发环境搭建以及第一个Dapp

本文包括三个部分:

1. 开发环境搭建

包括安装IDE和Geth。

1.1 安装Solidity

初学者建议直接使用 Remix -Solidity IDE(http://remix.ethereum.org/ )进行开发,可快速入门。

Remix 是一个基于浏览器的Solidity IDE,这样就可以不用安装Solidity。

自己安装可参考:https://solidity.readthedocs.io/en/develop/installing-solidity.html

1.2 安装Geth

Geth是以太坊客户端。

1.2.1 Mac下Geth安装

> brew tap ethereum/ethereum
> brew install ethereum

1.2.2 Windows下Geth安装

1. 在 https://geth.ethereum.org/downloads/ 下载安装包
2. 解压缩,执行geth.exe

更多平台安装方法请参考:https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum

1.3 环境准备

1、启动环境

geth --dev --datadir devNet  console 2>> dev.log

参数说明(更多命令:http://www.zgljl2012.com/yi-tai-fang-ke-hu-duan-gethming-ling-xiang-jie-zhong-wen/):

–dev 启用开发者模式,开发者模式会使用POA共识,默认预分配一个开发者账户并且会自动开启挖矿。

–datadir 后面的参数是区块数据及秘钥存放目录。第一次输入命令后,它会放在当前目录下新建一个testNet目录来存放数据。

console 进入控制台

2>> dev.log 表示把控制台日志输出到test.log文件

可新开一个命令行终端(最好使用可分屏的终端),实时显示日志:

> tail -f dev.log

2. 开发环境的账户

接下来,我们准备一下以太坊账户。

2.1 查询账户

我们使用的是开发环境,启动环境后会默认分配一个开发者账户,下面我们看看这个账户。在console中输入:

> eth.accounts

输出结果如下:

> eth.accounts
["0xce4ea4f2e55945b8d172c2f37c9419dcf9b07b3b"]

这就是我们的账户。下面我们看看这个账户里还有多少钱,输入命令:

> eth.getBalance(eth.accounts[0])

结果如下:

> eth.getBalance(eth.accounts[0])
1.15792089237316195423570985008687907853269984665640564039457584007913129639927e+77

可以看到末尾的e+77,表明这是一个很大的数,为了方便开发调试,我们需要新建一个账户,给它一个整数好算的初始余额。

2.2 创建账户

> personal.newAccount("xiaoming")
"0xb61d5def640f7eb96086031f2319225012967cb3"

就这样,我们给小明(为了方便表述,我们给新账户取个熟悉的名字)创建了一个账户。请注意,xiaoming不是账户名,是账户的密码(等一下还有用)。0xb61d5def640f7eb96086031f2319225012967cb3,这一串才是账户名。

接下来,看看新账户的余额:

> eth.getBalance(eth.accounts[1])
0

嗯,余额为0,符合期望。请注意,eth.accounts[1]表示我们查询的是第2个账户。

2.3 转账

好了,接下来该给小明充钱了,我们的初始账户有很多钱,就从它的里面给小明转账。命令如下:

> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(100, "ether")})

好了,再查一下小明的账户:

> eth.getBalance(eth.accounts[1])
100000000000000000000

小明现在有100个以太币了。如果对数据这么大不了解,我这边附录一份以太币单位:

Unit Wei Value Wei
wei 1 1 wei
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

我们转账时用的单位是ether,所以100后面会带这么多 0

2.4 解锁账户

为了给账户部署合约,首先我们需要给账户解锁,就像你需要往保险柜里放一份合约,首先要打开保险柜一样。

> personal.unlockAccount(eth.accounts[1], "xiaoming")
true

如前所述,xiaoming是账户密码。输出true,表示解锁成功。

3. 编写智能合约

重头戏开场。

3.1 第一个智能合约代码

接下来代码就不是写在终端里了,而是写在 Remix Solidity IDE 中。

pragma solidity ^0.4.18;
contract HelloWorld {
    string msg;
    
    function HelloWorld(string _msg) public {
        msg = _msg;
    }

    function say() constant public returns (string) {
        return msg;
    }
}

在这段代码中,我们定义了一份名为HelloWorld的合约,合约初始化时会传入一个字符串,然后在调用say时返回。

3.2 部署合约

首先点击IDE右边栏的Start to compile,然后点击IDE右边栏中的 detail 按钮,会弹出一个框,里面有一项叫:WEB3DEPLOY ,这是合约部署代码。如下:
以太坊智能合约开发环境搭建以及第一个Dapp

点击那个“拷贝”的小按钮,可以拷贝代码,将代码拷贝到编辑器,然后修改:

  • 1. 将第一行的var _msg = /* var of type string here */改为var —_msg = "hello world"
  • 2. 将 from: web3.eth.accounts[0] 改为 web3.eth.accounts[1]
var _msg = "hello world" ;
var helloworldContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_msg","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
var helloworld = helloworldContract.new(
   _msg,
   {
     from: web3.eth.accounts[1], 
     data: '0x608060405234801561001057600080fd5b506040516102a83803806102a8833981018060405281019080805182019291905050508060009080519060200190610049929190610050565b50506100f5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061009157805160ff19168380011785556100bf565b828001600101855582156100bf579182015b828111156100be5782518255916020019190600101906100a3565b5b5090506100cc91906100d0565b5090565b6100f291905b808211156100ee5760008160009055506001016100d6565b5090565b90565b6101a4806101046000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063954ab4b214610046575b600080fd5b34801561005257600080fd5b5061005b6100d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009b578082015181840152602081019050610080565b50505050905090810190601f1680156100c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b606060008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561016e5780601f106101435761010080835404028352916020019161016e565b820191906000526020600020905b81548152906001019060200180831161015157829003601f168201915b50505050509050905600a165627a7a72305820c25566663a8c1c203302ed3c4e0786b86d95e4f742524aa45b59432227c59bd70029', 
     gas: '4700000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

将这段代码拷贝到 Geth 客户端,回车确定。成功后将看到:

Contract mined! address: 0x40d619f1b9045000fd66b3db4a9c50b543d6530e transactionHash: 0x753fe3640423f3f30a584c31b3f98812eb7ea5e798b1b726b98c6d7373fe547a

接下来,运行一下合约:

> helloworld.say()
"hello world"

合约部署成功!

同时,可以再看一下余额:

> eth.getBalance(eth.accounts[1])
99999999999999799431

因为部署合约,我们已经花掉部分(看一看部署代码中的gas)钱了。

上一篇:java循环练习:用户输入一个10以内的数字,通过运算求出该数字的阶乘


下一篇:脚本,函数