罗韭菜的超详细dapp从零实战(二)-- 编写智能合约与truffle

使用solidity语言撰写智能合约

  • Ethereum上的智能合约需要使用solidity语言来撰写。虽然还有其他能用来撰写智能合约的语言如Serpent(类Python)、lll(类Fortran)

  • 但目前看到所有公开的智能合约都是使用solidity撰写。

  • solidity还是比较像Java或C#。因为和Javascript不同,solidity与Java或C#同属于强类型(Strong Type,在定义变数时需要指定类型)语言、在定义函式(function)时同样需指定回传的类型(type)、同样也需要先编译才能执行。这些特性都是Javascript所不具备的。

关于solidity编写智能合约的具体语法参见笔者专题

开发前的准备

  • 本文将使用当前最活跃的智能合约开发框架truffle为基础来开发。ENS(Ethereum Name Service)也是采用truffle框架。其他选择还有embark等。

  • 测试网:test rpc。 毕竟真实网络需要以太币,且操作需要等待十几秒,性价比不高。testrpc中也包含了Javascript版本的Ethereum虚拟机(Ethereum Virtual Machine),因此可以完整地执行智能合约。
    -编译器: atom,好处之前说过

环境准备

  • node.js (自行安卓)
  • 安装truffle
$ npm install -g ethereumjs-testrpc truffle
  • 启动testrpc
luoxuedeMBP:~ luoxue$ testrpc
EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2)

Available Accounts
==================
(0) 0x48e9abd440ff12f0f5bd457d0205d64a2c047973
(1) 0x14692d8b82328f29016db341c15f59585531ab58
(2) 0x0ff04903afd3dc4791ea5b747804de6cd6c4c513
(3) 0x4d77b3d7cadee90f4c90af72be75bd2ac88a72b5
(4) 0xc66ad1ee63b457047e7102425e657b70105f5eb9
(5) 0xfab642ee1cbacd8fc678c83e821f7d8beda61fec
(6) 0xf76e1c57250b88c1628430d0c04e3b4ecb111c0e
(7) 0xf4994bfce769c16f1631f0609867858a96885917
(8) 0xf31105aee2b095265ea46c51e2644eacbab96cb7
(9) 0x51213b5aa72783e7216b55fc2ecb3104dfd5f465

Private Keys
==================
(0) 77b92fa8bdf4bec94f3ebf67f44fb11ff660911ca64d3aa2c729b689aa8c807b
(1) e1b555743af9cc58fb094349776f944b76ff85663b51d5d6bc4802da2e92c54c
(2) c5180d4154bb2d89eb89335766070dcc8210b25374ef8d71c26f50d002f3c450
(3) 61acc2eaf3fdcecad846cf0507ae8cc07fa03a9bf00a581974c268c6bcba0afd
(4) 7f384dad1148c73257c596bc875ca492e8c6e99bb5f7de6958ea4cfe82a5b9a3
(5) 9796225e8d81a3f72e4fccfe3a562838bf589d4c40fcadbdc85c9b9ad5d5ad4c
(6) b858608913552368f4bdbc33a01f7fc7ec98684b013eab2d8dcb696246cbea56
(7) 3b581c0f56aa9937706cd0e27e7a1ccd45513c71d845ab5b18ff5039c20e9d8a
(8) f5d548c0b0c9974711814937b2d0d8373e244aa265ac2e0174b2b9ec35faa134
(9) 22cb6ad0b97dda82426c04485fca580f25746602bc94950efcb13d10528bf622

HD Wallet
==================
Mnemonic:      marriage artwork corn dentist other feel decrease pride brass flash wire since
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545

  • testrpc启动后自动建立了10个帐号(Accounts),与每个帐号对应的私钥(Private Key)。
  • 每个帐号中都有100个测试用的以太币(Ether)。
  • 要注意testrpc仅运行在內存中,因此每次重开时都会回到全新的状态。

建立项目

输入以下命令

luoxuedeMBP:~ luoxue$ cd desktop
luoxuedeMBP:desktop luoxue$ mkdir SmartContractDemo
luoxuedeMBP:desktop luoxue$ cd SmartContractDemo
luoxuedeMBP:SmartContractDemo luoxue$ mkdir hello
luoxuedeMBP:SmartContractDemo luoxue$ cd hello
luoxuedeMBP:hello luoxue$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!

Commands:

  Compile:        truffle compile
  Migrate:        truffle migrate
  Test contracts: truffle test
luoxuedeMBP:hello luoxue$ ls

目录结构:

  • /contracts:存放智能合约原始代码的地方
  • /migrations:这是 Truffle用来部署智能合约的功能,待会儿我们会修改2_deploy_contracts.js来部署 HelloWorld.sol。
  • /test: 测试智能合约的代码放在这里,支持js 与 sol 测试。
  • truffle.js: Truffle 的设置文档

新建HelloWorld.sol
放在contracts里,代码如下

pragma solidity ^0.4.4;

contract HelloWorld {
  function sayHello() returns (string) {
    return ("Hello World");
  }
}

编译
现在执行truffle compile命令,我们可以将HelloWorld.sol原始码编译成Ethereum bytecode。

luoxuedeMBP:hello luoxue$ cd build
luoxuedeMBP:build luoxue$ ls
contracts
luoxuedeMBP:build luoxue$ cd contracts
luoxuedeMBP:contracts luoxue$ ls
HelloWorld.json Migrations.json
  • 编译成功,新增了build文件夹,会在HelloWorld文件夹下面的build/contracts文件夹下面看见HelloWorld.json文件。


    image.png

部署

  • 复制migration文件夹中的init文件,创建名为2_deploy_contracts.js的文件,代码如下:
var HelloWorld = artifacts.require("HelloWorld");
module.exports = function(deployer) {
  deployer.deploy(HelloWorld);
};
  • 使用artifacts.require语句来取得准备部署的合约。使用deployer.deploy语句将合约部署到区块链上。这边HelloWorld是contract的名称而不是文件名。因此可以用此语法读入任一.sol文件中的任一合约。

  • 现在执行truffle migrate命令

  • 注意!!!需要切换到truffle develop 网络下编译和部署,并且部署文件需要在编译前写对,因为编译即产生一个合约地址,错误的部署文件会对不上
    姿势如下:

luoxuedeMBP:HelloWorld luoxue$ truffle develop
省略
truffle(develop)> compile
Compiling ./contracts/HelloWorld.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts

truffle(develop)> migrate
Using network 'develop'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0xad8b447607866b32b1c115156a97f9d247a125d35c14585ac3ed3f9eaa06a528
  Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Saving successful migration to network...
  ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying HelloWorld...
  ... 0xae7215511d62acedac6c4880d8578240e73913373eaaf6d0e86253197b35261b
  HelloWorld: 0x345ca3e014aaf5dca488057592ee47305d9b3e10
Saving successful migration to network...
  ... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0
Saving artifacts...
truffle(develop)> 

获取合约对象

  • 通过web3 来获取合约对象
  • 输入
// 声明一个对象
truffle(develop)> let contract;
undefined
// 实例化
// truffle console
truffle(develop)> HelloWorld.deployed().then(instance => contract = instance)

  • 解释:truffle console中预载了truffle-contract函数库,以方便操作部署到区块链上的合约。

  • 这边使用HelloWorld.deployed().then语句来取得HelloWorld合约的Instance(实例),并存到contract变量中,以方便后续的调用。

  • 使用的是js es6+语句

调用合约函数

truffle(develop)> contract.sayHello()
'Hello World'
  • 注意如果该函数没有constant 或者pure ,需要.call()
    如将代码增加一个函数无pure/constant如下:
pragma solidity ^0.4.4;

contract HelloWorld {
  // 能直接调用
  function sayHello() pure public returns (string) {
    return ("Hello World");
  }
  // 需要依靠.call调用
  function test() public returns (string) {
    return ("Hello World");
  }
}
  • 重新编译与部署, 注意部署时候需要加上-- reset
 // 编译
truffle(develop)> compile
Compiling ./contracts/HelloWorld.sol...

Compilation warnings encountered:

/Users/luoxue/Desktop/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol:9:3: Warning: Function state mutability can be restricted to pure
  function test() public returns (string) {
  ^ (Relevant source part starts here and spans across multiple lines).

Writing artifacts to ./build/contracts
// 部署
truffle(develop)> migrate
Using network 'develop'.

Network up to date.
truffle(develop)> migrate --reset

正确的调用姿势

truffle(develop)> contract.sayHello()
'Hello World'
truffle(develop)> contract.test.call()
'Hello World'
truffle(develop)> 
  • 输入与输出,在代码里面加入一个echo函数,输入字符串,返回输出
function echo(string s) public returns (string) {
    return s;
  }
truffle(develop)> contract.echo.call("melody")
'melody'
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容