1.学习目标

  1. 了解智能合约
  2. 简单环境搭建
  3. 能够利用solidity编写Hello World合约
  4. 合约部署
  5. 和合约互动

2.使用solidity语言撰写智能合约

Ethereum上的智能合约需要使用solidity语言来撰写。solidity是一种类似Javsscript的语言,而且围绕着solidity的各种开发工具链,都是使用属于Javascript生态系的npm来提供的。但solidity在语法上比较像Java或C#,因为和Javascript不同,solidity与Java或C#同属于强类型语言,、在定义函数时同样需要指定回传的类型、同样也需要先编译才能执行。这些特性都是Javascript所不具备的。

3.开发前的准备

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

开发过程中,我们将使用testrpc工具在电脑上模拟智能合约所需的以太坊内存块链测试环境。

testrpc中也包含了Javascript版本的Ethereum虚拟机(Ethereum Virtual Machine),因此可以完整地执行智能合约。

代码编辑器使用Atom,搭配solidity插件来开发。Atom是Github为开发者设计的基于Chromium的编辑器,支持NodeJS写的插件,内置Git,使用MIT协议开源发布。solidity插件除了支持语法高亮之外,也会透过Solium检查并提示基本的语法错误,相当方便。其他编辑器应该也有类似的插件可选择。

4.Ubuntu环境下Atom编辑器安装及使用

sudo add-apt-repository ppa:webupd8team/atom
sudo apt-get update
sudo apt-get install atom

安装插件linter-solidity、autocomplete-solidity、linter-solium以方便solidity代码编写。

5.安装所需工具

首先安装Node.js

安装nvm

cd ~
mkdir .nvm
cd .nvm
git clone https://github.com/creationix/nvm

等待下载完毕后source ~/.nvm/nvm/nvm.sh添加到~/.profile之类的文件中

vim ~/.profile

并在文件末尾添加source ~/.nvm/nvm/nvm.sh

source ~/.profile
nvm --version

检查安装是否正确

安装node

nvm install node
node --version

安装npm

git clone --recursive git://github.com/isaacs/npm.git
cd npm/bin
node npm-cli.js install npm -g
npm --version

安装ethereumjs-testrpc和truffle

npm install -g ethereumjs-testrpc truffle
sily@lyg-sily:~$ npm install -g ethereumjs-testrpc truffle/home/sily/.nvm/nvm/versions/node/v9.3.0/bin/testrpc -> /home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/ethereumjs-testrpc/build/cli.node.js
/home/sily/.nvm/nvm/versions/node/v9.3.0/bin/truffle -> /home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/truffle/build/cli.bundled.js
+ ethereumjs-testrpc@6.0.3
+ truffle@4.0.4
added 343 packages in 115.81s

启动testrpc

安装好后随时可以使用testrpc命令来启动以太坊测试环境。

sily@lyg-sily:~$ testrpc
EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2)Available Accounts
==================
(0) 0x7e1897cec8e1a098384d17e85a9cd348ccb92b4a
(1) 0x6c96c6cb16442ab83aea0eb1bc3a183e28a922fe
(2) 0x163f0e06082c5cd14ff56658b186a30b0f6e7d9f
(3) 0x0e9558b2cb935ab26484c3d6783fbf2fe70041c8
(4) 0xa2233f08bbb7e3a826cc4c2cede22caf3a6922e6
(5) 0x3b1317510218f98946e0fb72b1a0685ac00bcbc4
(6) 0xca33f56a03e5ae86e25655f4dd7de88be12ec184
(7) 0xfb56aed85dd00908f1e0729ed80d06f456898588
(8) 0x6cfe240b49a28986057016ef2ecd9d6711f6b632
(9) 0x0e866473d6776edc39935dd5d00425b6ab2a423aPrivate Keys
==================
(0) 3ae87bfaeabf103ce723b78525ab1278b2c7652b93b99a0131321adaa7000537
(1) 2f23eaef51f941b7af171a56acbd7524554ad529236b6abb6920935218f5df58
(2) 9b5b5d42786e74364e80b45ecf1a2b7201db7eafe12684f71006fbe3368e6dfe
(3) 33181b42772371fad50f29b8377f7a3de72000397f9b021677e329bede7bfcc7
(4) 3f5f366d89ab9263b92f35368840d24d562af043db8a5ad773dc8cc8f122662d
(5) 29933e3e79129da23da3cc0f5cecb03c583c3ad6c4c1ad8a39d68386fe92d91b
(6) 7e9bd47a6120bb9a240a96ce80866b98646f07cb98197bdffec389805575144b
(7) 0c7144621371a04e4ee733d06482b0a23ed775af17172e75e26f2b8915814e35
(8) 60ab702bdad5a348645f65fb0678cafec891c534964982d97b96f4a57abd78ef
(9) 8ff45f1ccb23bec8a317a6e218b3b50290646317b5c809c797e1522bcef9d031HD Wallet
==================
Mnemonic:      vapor high liberty evoke pledge bronze critic stomach neck figure recipe mind
Base HD Path:  m/44'/60'/0'/0/{account_index}Listening on localhost:8545

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

一切就绪,我们可以开始建立第一个智能合约项目了。

6.建立项目

开启另一个终端,输入以下命令以建立项目:

sily@lyg-sily:~$ mkdir SmartContractDemo
sily@lyg-sily:~$ cd SmartContractDemo/
sily@lyg-sily:~/SmartContractDemo$ mkdir HelloWorld
sily@lyg-sily:~/SmartContractDemo$ cd HelloWorld/
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!Commands:Compile:        truffle compileMigrate:        truffle migrateTest contracts: truffle test
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ ls
contracts  migrations  test  truffle-config.js  truffle.js
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ 

目录结构

/contracts:存放智能合约原始代码的地方,可以看到里面有个Migrations.sol文件,我们的HelloWorld.sol文件就存放在这里。

/migrations:这是Truffle用来部署智能合约的功能,待会儿我们会修改2_deploy_contracts.js来部署HelloWorld.sol

/test:测试智能合约的代码放在这里,支持jssol测试。

truffle.js:Truffle的设置文档。

7.新建HelloWorld合约

contracts文件夹下新建HelloWorld.sol文件,当然也可以直接在HelloWorld路径下面直接执行truffle create contract HelloWorld命令来创建HelloWorld.sol

sily@lyg-sily:~/SmartContractDemo/HelloWorld$ ls
contracts  migrations  test  truffle-config.js  truffle.js
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle create contract HelloWorld
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ cd contracts/
sily@lyg-sily:~/SmartContractDemo/HelloWorld/contracts$ ls
HelloWorld.sol  Migrations.sol
sily@lyg-sily:~/SmartContractDemo/HelloWorld/contracts$ 

HelloWorld.sol的文件内容如下:

pragma solidity ^0.4.4;contract HelloWorld {function sayHello() returns (string) {return ("Hello World");}
}

代码说明

pragma solidity ^0.4.4;

第一行表明目前使用的solidity版本,不同版本的solidity可能会编译出不同的bytecode^代表兼容solidity 0.4.4~0.4.9的版本。

contract HelloWorld {...
}

contract关键字类似于其他语言中较常见的class。因为solidity是专为智能合约(Contract)设计的语言,声明contract后即内置了开发智能合约所需的功能。也可以把这句理解为

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

函数的结构与其他程序类似,但如果有传入的参数或回传值,需要指定参数或回传值的类型(type)。

8.编译

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

sily@lyg-sily:~/SmartContractDemo/HelloWorld$ ls
contracts  migrations  test  truffle-config.js  truffle.js
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle compile
Compiling ./contracts/HelloWorld.sol...
Compiling ./contracts/Migrations.sol...Compilation warnings encountered:/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol:4:3: Warning: No visibility specified. Defaulting to "public".function sayHello() returns (string) {^
Spanning multiple lines.
,/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol:4:3: Warning: Function state mutability can be restricted to purefunction sayHello() returns (string) {^
Spanning multiple lines.Writing artifacts to ./build/contractssily@lyg-sily:~/SmartContractDemo/HelloWorld$ ls
build  contracts  migrations  test  truffle-config.js  truffle.js

编译成功后,会在HelloWorld文件夹下面的build/contracts文件夹下面看见HelloWorld.json文件。

9.部署

truffle框架中提供了方便部署合约的脚本。打开migrations/2_deploy_contracts.js文件(脚本使用Javascript编写),将内容修改如下:

var HelloWorld = artifacts.require("HelloWorld");
module.exports = function(deployer) {deployer.deploy(HelloWorld);
};

使用artifacts.require语句来取得准备部署的合约。使用deployer.deploy语句将合约部署到区块链上。这边HelloWorldcontract的名称而不是文件夹。因此可以用此语法读入任一.sol文件中的任一合约。

现在执行truffle migrate命令:

sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle migrate
Compiling ./contracts/HelloWorld.sol...Compilation warnings encountered:/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol:4:3: Warning: Function state mutability can be restricted to purefunction sayHello() public constant returns (string) {^
Spanning multiple lines.Writing artifacts to ./build/contractsError: No network specified. Cannot determine current network.at Object.detect (/home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/truffle/build/cli.bundled.js:41338:23)at /home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/truffle/build/cli.bundled.js:202239:19at /home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/truffle/build/cli.bundled.js:41263:11at /home/sily/.nvm/nvm/versions/node/v9.3.0/lib/node_modules/truffle/build/cli.bundled.js:41295:9at <anonymous>

可以发现,此时在使用truffle migrate进行智能合约test环境发布时出现异常,原因是truffle.js里面未配置链接合约发布时的环境地址,找到对应的truffle.js文件,修改代码为类似如下配置即可解决问题:

module.exports = {networks: {development: {host: "localhost",port:8545,network_id:"*"  // 匹配任何network id}}
};

重新执行truffle migrate:

sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle migrate
Using network 'development'.Running migration: 1_initial_migration.jsDeploying Migrations...... 0xd43c42b526addb75876bb26a3086cabf79eaf9b0dbb1cd18ce3d6cc78f8e5335Migrations: 0x69c7674e74ee9aee187ea05b97faf08d6a7c0b94
Saving successful migration to network...... 0x4aa706f72045aec809b3ab5d286489c157e6f5e73e1538a441cfb199c512f849
Saving artifacts...
Running migration: 2_deploy_contracts.jsDeploying HelloWorld...... 0x35afc83dd8e594167f1ddb9f52250b02aa72508a9b77ad15f5bd58b19a1e7275HelloWorld: 0x93ca4fd7d2820b2156fd88e40783ac9a41e26cfe
Saving successful migration to network...... 0x12174aa188a4c47f84e071356149dfc9a51942bd81ce53d84bb22225d18d2fae
Saving artifacts...
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ 

如此以后,合约已经部署到testrpc中。切换到testrpc窗口,可以看到testrpc有反应了。

Listening on localhost:8545
net_version
eth_accounts
eth_accounts
net_version
net_version
eth_sendTransactionTransaction: 0xd43c42b526addb75876bb26a3086cabf79eaf9b0dbb1cd18ce3d6cc78f8e5335Contract created: 0x69c7674e74ee9aee187ea05b97faf08d6a7c0b94Gas usage: 269607Block Number: 1Block Time: Wed Jan 10 2018 20:19:00 GMT+0800 (CST)eth_newBlockFilter
eth_getFilterChanges
eth_getTransactionReceipt
eth_getCode
eth_uninstallFilter
eth_sendTransactionTransaction: 0x4aa706f72045aec809b3ab5d286489c157e6f5e73e1538a441cfb199c512f849Gas usage: 41981Block Number: 2Block Time: Wed Jan 10 2018 20:19:01 GMT+0800 (CST)eth_getTransactionReceipt
eth_accounts
net_version
net_version
eth_sendTransactionTransaction: 0x35afc83dd8e594167f1ddb9f52250b02aa72508a9b77ad15f5bd58b19a1e7275Contract created: 0x93ca4fd7d2820b2156fd88e40783ac9a41e26cfeGas usage: 142468Block Number: 3Block Time: Wed Jan 10 2018 20:19:01 GMT+0800 (CST)eth_newBlockFilter
eth_getFilterChanges
eth_getTransactionReceipt
eth_getCode
eth_uninstallFilter
eth_sendTransactionTransaction: 0x12174aa188a4c47f84e071356149dfc9a51942bd81ce53d84bb22225d18d2faeGas usage: 26981Block Number: 4Block Time: Wed Jan 10 2018 20:19:01 GMT+0800 (CST)eth_getTransactionReceipt

10.与合约互动

truffle提供命令行工具,执行truffle console命令后,可用Javascript来和刚刚部署的合约互动。

sily@lyg-sily:~/SmartContractDemo/HelloWorld$ ls
build  contracts  migrations  test  truffle-config.js  truffle.js
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle console
truffle(development)> let contract
undefined
truffle(development)> HelloWorld.deployed().then(instance => contract = instance)
TruffleContract {constructor: { [Function: TruffleContract]_static_methods: { setProvider: [Function: setProvider],new: [Function: new],at: [Function: at],deployed: [Function: deployed],defaults: [Function: defaults],hasNetwork: [Function: hasNetwork],isDeployed: [Function: isDeployed],detectNetwork: [Function: detectNetwork],setNetwork: [Function: setNetwork],resetAddress: [Function: resetAddress],link: [Function: link],clone: [Function: clone],addProp: [Function: addProp],toJSON: [Function: toJSON] },_properties: { contract_name: [Object],contractName: [Object],abi: [Object],network: [Function: network],networks: [Function: networks],address: [Object],links: [Function: links],events: [Function: events],binary: [Function: binary],deployedBinary: [Function: deployedBinary],unlinked_binary: [Object],bytecode: [Object],deployedBytecode: [Object],sourceMap: [Object],deployedSourceMap: [Object],source: [Object],sourcePath: [Object],ast: [Object],compiler: [Object],schema_version: [Function: schema_version],schemaVersion: [Function: schemaVersion],updated_at: [Function: updated_at],updatedAt: [Function: updatedAt] },_property_values: {},_json: { contractName: 'HelloWorld',abi: [Array],bytecode: '0x6060604052341561000f57600080fd5b6101578061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc610117565b6040805190810160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820b98aa7cabcef6181bb855c27290b86a3ed577c3493b6cf1cebfeb4be9a990c2e0029',deployedBytecode: '0x606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610046575b600080fd5b341561005157600080fd5b6100596100d4565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009957808201518184015260208101905061007e565b50505050905090810190601f1680156100c65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100dc610117565b6040805190810160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820b98aa7cabcef6181bb855c27290b86a3ed577c3493b6cf1cebfeb4be9a990c2e0029',sourceMap: '25:112:0:-;;;;;;;;;;;;;;;;;',deployedSourceMap: '25:112:0:-;;;;;;;;;;;;;;;;;;;;;;;;49:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:86:0;94:6;;:::i;:::-;108:22;;;;;;;;;;;;;;;;;;;;49:86;:::o;25:112::-;;;;;;;;;;;;;;;:::o',source: 'pragma solidity ^0.4.4;\n\ncontract HelloWorld {\n  function sayHello() public constant returns (string) {\n    return ("Hello World");\n  }\n}\n',sourcePath: '/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol',ast: [Object],compiler: [Object],networks: [Object],schemaVersion: '1.0.1',updatedAt: '2018-01-10T12:19:01.841Z' },setProvider: [Function: bound setProvider],new: [Function: bound new],at: [Function: bound at],deployed: [Function: bound deployed],defaults: [Function: bound defaults],hasNetwork: [Function: bound hasNetwork],isDeployed: [Function: bound isDeployed],detectNetwork: [Function: bound detectNetwork],setNetwork: [Function: bound setNetwork],resetAddress: [Function: bound resetAddress],link: [Function: bound link],clone: [Function: bound clone],addProp: [Function: bound addProp],toJSON: [Function: bound toJSON],web3: Web3 {_requestManager: [RequestManager],currentProvider: [Provider],eth: [Eth],db: [DB],shh: [Shh],net: [Net],personal: [Personal],bzz: [Swarm],settings: [Settings],version: [Object],providers: [Object],_extend: [Function] },class_defaults: { from: '0x7e1897cec8e1a098384d17e85a9cd348ccb92b4a',gas: 6721975,gasPrice: 100000000000 },currentProvider: HttpProvider {host: 'http://localhost:8545',timeout: 0,user: undefined,password: undefined,send: [Function],sendAsync: [Function],_alreadyWrapped: true },network_id: '1515578597496' },abi: [ { constant: true,inputs: [],name: 'sayHello',outputs: [Array],payable: false,stateMutability: 'view',type: 'function' } ],contract: Contract {_eth: Eth {_requestManager: [RequestManager],getBalance: [Function],getStorageAt: [Function],getCode: [Function],getBlock: [Function],getUncle: [Function],getCompilers: [Function],getBlockTransactionCount: [Function],getBlockUncleCount: [Function],getTransaction: [Function],getTransactionFromBlock: [Function],getTransactionReceipt: [Function],getTransactionCount: [Function],call: [Function],estimateGas: [Function],sendRawTransaction: [Function],signTransaction: [Function],sendTransaction: [Function],sign: [Function],compile: [Object],submitWork: [Function],getWork: [Function],coinbase: [Getter],getCoinbase: [Function],mining: [Getter],getMining: [Function],hashrate: [Getter],getHashrate: [Function],syncing: [Getter],getSyncing: [Function],gasPrice: [Getter],getGasPrice: [Function],accounts: [Getter],getAccounts: [Function],blockNumber: [Getter],getBlockNumber: [Function],protocolVersion: [Getter],getProtocolVersion: [Function],iban: [Function],sendIBANTransaction: [Function: bound transfer] },transactionHash: null,address: '0x93ca4fd7d2820b2156fd88e40783ac9a41e26cfe',abi: [ [Object] ],sayHello: { [Function: bound ]request: [Function: bound ],call: [Function: bound ],sendTransaction: [Function: bound ],estimateGas: [Function: bound ],getData: [Function: bound ],'': [Circular] },allEvents: [Function: bound ] },sayHello: { [Function]call: [Function],sendTransaction: [Function],request: [Function: bound ],estimateGas: [Function] },sendTransaction: [Function],send: [Function],allEvents: [Function: bound ],address: '0x93ca4fd7d2820b2156fd88e40783ac9a41e26cfe',transactionHash: null }
truffle(development)> contract.sayHello.call()
'Hello World'
truffle(development)> 

truffle console中预载了truffle-contract函数库,以方便操作部署到区块链上的合约。使用了HelloWorld.deployed().then语句来取得HelloWorld合约的Instance(实例),并存到contract变量中,以方便后续的调用。

上面用的是Javascript ES6+的语法,这句也可以写成:

HelloWorld.deployed().then(instance => {contract = instance
});

还可以用ES5的写法:

HelloWorld.deployed().then(function(instance) {hello = instance;
});
truffle(development)> contract.sayHello.call()
'Hello World'

最后通过contract.sayHello.call()成功打印出"Hello World",这里直接调用contract.sayHello()也会得到一样的结果。truffle-contract提供使用call()来读取只读(read only)的数据,这样就不需提供gas。因此如果遇到的操作需要向区块链写入数据,我们就不能用call语句了。

这样,我们的第一个智能合约就已经写好并部署好了,也验证了合约确实可以运行。

11.加入新方法

我们在HelloWorld.sol中再加入一个echo方法,echo方法接受一个参数,并回传传送的参数。

function echo(string name) constant returns (string) {
    return name;
}

新的echo方法中传入了一个name参数。我们也为echo方法加入一个constant声明,表示调用这个方法并不会改变区块链的状态。如此一来,透过truffle-contract来调用此方法时,会自动选用call来呼叫,也不需要额外提供gas

由于更新了合约内容,我们需要先重新编译一次,将编译结果部署到testrpc上,再通过truffle console执行查看结果。

sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle migrate --reset
Compiling ./contracts/HelloWorld.sol...Compilation warnings encountered:/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol:4:3: Warning: Function state mutability can be restricted to purefunction sayHello() public constant returns (string) {^
Spanning multiple lines.
,/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol:8:3: Warning: Function state mutability can be restricted to purefunction echo(string name) public constant returns (string) {^
Spanning multiple lines.Writing artifacts to ./build/contractsUsing network 'development'.Running migration: 1_initial_migration.jsReplacing Migrations...... 0xfc5af4b443dcae96f96206e26d2bc93b9699e7d14980dd0247baea112bd04c44Migrations: 0xee671e4bb1e86df24120041587b0a4841924f7bd
Saving successful migration to network...... 0x1d7e34e903cc04a5e5cd6e5cca1031034841bd001dd693b488500fe75c4df9e2
Saving artifacts...
Running migration: 2_deploy_contracts.jsReplacing HelloWorld...... 0xdb8c8ef861498972ad769f947e9c03872b3f17f7292deff3fa25d5f5318ce94fHelloWorld: 0xace9ff211c9131362e05774335c6b3a353739119
Saving successful migration to network...... 0x3a653f82abd0b92f389ea78ba654f51ff2256961f72b280874676cebac24f895
Saving artifacts...
sily@lyg-sily:~/SmartContractDemo/HelloWorld$ truffle console
truffle(development)> let contract
undefined
truffle(development)> HelloWorld.deployed().then(instance => contract = instance)
TruffleContract {constructor: { [Function: TruffleContract]_static_methods: { setProvider: [Function: setProvider],new: [Function: new],at: [Function: at],deployed: [Function: deployed],defaults: [Function: defaults],hasNetwork: [Function: hasNetwork],isDeployed: [Function: isDeployed],detectNetwork: [Function: detectNetwork],setNetwork: [Function: setNetwork],resetAddress: [Function: resetAddress],link: [Function: link],clone: [Function: clone],addProp: [Function: addProp],toJSON: [Function: toJSON] },_properties: { contract_name: [Object],contractName: [Object],abi: [Object],network: [Function: network],networks: [Function: networks],address: [Object],links: [Function: links],events: [Function: events],binary: [Function: binary],deployedBinary: [Function: deployedBinary],unlinked_binary: [Object],bytecode: [Object],deployedBytecode: [Object],sourceMap: [Object],deployedSourceMap: [Object],source: [Object],sourcePath: [Object],ast: [Object],compiler: [Object],schema_version: [Function: schema_version],schemaVersion: [Function: schemaVersion],updated_at: [Function: updated_at],updatedAt: [Function: updatedAt] },_property_values: {},_json: { contractName: 'HelloWorld',abi: [Array],bytecode: '0x6060604052341561000f57600080fd5b6102488061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610051578063f15da729146100df575b600080fd5b341561005c57600080fd5b6100646101b5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100a4578082015181840152602081019050610089565b50505050905090810190601f1680156100d15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100ea57600080fd5b61013a600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101f8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017a57808201518184015260208101905061015f565b50505050905090810190601f1680156101a75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101bd610208565b6040805190810160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b610200610208565b819050919050565b6020604051908101604052806000815250905600a165627a7a72305820ce2a412dd03391bea1a4d86dcaa57502a5d812ad4005a99570a2bb3b3ffd25ec0029',deployedBytecode: '0x60606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610051578063f15da729146100df575b600080fd5b341561005c57600080fd5b6100646101b5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100a4578082015181840152602081019050610089565b50505050905090810190601f1680156100d15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100ea57600080fd5b61013a600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101f8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017a57808201518184015260208101905061015f565b50505050905090810190601f1680156101a75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101bd610208565b6040805190810160405280600b81526020017f48656c6c6f20576f726c64000000000000000000000000000000000000000000815250905090565b610200610208565b819050919050565b6020604051908101604052806000815250905600a165627a7a72305820ce2a412dd03391bea1a4d86dcaa57502a5d812ad4005a99570a2bb3b3ffd25ec0029',sourceMap: '25:198:0:-;;;;;;;;;;;;;;;;;',deployedSourceMap: '25:198:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:86:0;94:6;;:::i;:::-;108:22;;;;;;;;;;;;;;;;;;;;49:86;:::o;139:82::-;191:6;;:::i;:::-;212:4;205:11;;139:82;;;:::o;25:198::-;;;;;;;;;;;;;;;:::o',source: 'pragma solidity ^0.4.4;\n\ncontract HelloWorld {\n  function sayHello() public constant returns (string) {\n    return ("Hello World");\n  }\n\n  function echo(string name) public constant returns (string) {\n    return name;\n  }\n}\n',sourcePath: '/home/sily/SmartContractDemo/HelloWorld/contracts/HelloWorld.sol',ast: [Object],compiler: [Object],networks: [Object],schemaVersion: '1.0.1',updatedAt: '2018-01-10T13:34:12.869Z' },setProvider: [Function: bound setProvider],new: [Function: bound new],at: [Function: bound at],deployed: [Function: bound deployed],defaults: [Function: bound defaults],hasNetwork: [Function: bound hasNetwork],isDeployed: [Function: bound isDeployed],detectNetwork: [Function: bound detectNetwork],setNetwork: [Function: bound setNetwork],resetAddress: [Function: bound resetAddress],link: [Function: bound link],clone: [Function: bound clone],addProp: [Function: bound addProp],toJSON: [Function: bound toJSON],web3: Web3 {_requestManager: [RequestManager],currentProvider: [Provider],eth: [Eth],db: [DB],shh: [Shh],net: [Net],personal: [Personal],bzz: [Swarm],settings: [Settings],version: [Object],providers: [Object],_extend: [Function] },class_defaults: { from: '0x7e1897cec8e1a098384d17e85a9cd348ccb92b4a',gas: 6721975,gasPrice: 100000000000 },currentProvider: HttpProvider {host: 'http://localhost:8545',timeout: 0,user: undefined,password: undefined,send: [Function],sendAsync: [Function],_alreadyWrapped: true },network_id: '1515578597496' },abi: [ { constant: true,inputs: [],name: 'sayHello',outputs: [Array],payable: false,stateMutability: 'view',type: 'function' },{ constant: true,inputs: [Array],name: 'echo',outputs: [Array],payable: false,stateMutability: 'view',type: 'function' } ],contract: Contract {_eth: Eth {_requestManager: [RequestManager],getBalance: [Function],getStorageAt: [Function],getCode: [Function],getBlock: [Function],getUncle: [Function],getCompilers: [Function],getBlockTransactionCount: [Function],getBlockUncleCount: [Function],getTransaction: [Function],getTransactionFromBlock: [Function],getTransactionReceipt: [Function],getTransactionCount: [Function],call: [Function],estimateGas: [Function],sendRawTransaction: [Function],signTransaction: [Function],sendTransaction: [Function],sign: [Function],compile: [Object],submitWork: [Function],getWork: [Function],coinbase: [Getter],getCoinbase: [Function],mining: [Getter],getMining: [Function],hashrate: [Getter],getHashrate: [Function],syncing: [Getter],getSyncing: [Function],gasPrice: [Getter],getGasPrice: [Function],accounts: [Getter],getAccounts: [Function],blockNumber: [Getter],getBlockNumber: [Function],protocolVersion: [Getter],getProtocolVersion: [Function],iban: [Function],sendIBANTransaction: [Function: bound transfer] },transactionHash: null,address: '0xace9ff211c9131362e05774335c6b3a353739119',abi: [ [Object], [Object] ],sayHello: { [Function: bound ]request: [Function: bound ],call: [Function: bound ],sendTransaction: [Function: bound ],estimateGas: [Function: bound ],getData: [Function: bound ],'': [Circular] },echo: { [Function: bound ]request: [Function: bound ],call: [Function: bound ],sendTransaction: [Function: bound ],estimateGas: [Function: bound ],getData: [Function: bound ],string: [Circular] },allEvents: [Function: bound ] },sayHello: { [Function]call: [Function],sendTransaction: [Function],request: [Function: bound ],estimateGas: [Function] },echo: { [Function]call: [Function],sendTransaction: [Function],request: [Function: bound ],estimateGas: [Function] },sendTransaction: [Function],send: [Function],allEvents: [Function: bound ],address: '0xace9ff211c9131362e05774335c6b3a353739119',transactionHash: null }
truffle(development)> contract.echo("2018-1-10 blockchain")
'2018-1-10 blockchain'
truffle(development)> 

echo方法确实将我们输入的内容回传了。同时因为声明了constant,我们不需要直接调用call()方法,truffle会自动选用call来调用。

另外需要注意,如果我们还是使用truffle migrate命令,会得到如下信息:

$ truffle migrate
Using network 'development'.Network up to date.

Truffle会告诉你现在网络上的合约都已经是最新的,但事实上刚刚程序中新增的方法并没有更新到内存块链上。要更新内存块链上已部署的程序,需要改写migrations中的脚本,但现在还不到介绍migration的时候。还好我们开发用的内存块链是怎么修改都没关系的testrpc,可以使用truffle migrate --reset命令直接在testrpc上部署一次。

参考自:
http://blog.csdn.net/liyuechun520/article/details/78036363

带你玩转以太坊智能合约的Hello World相关推荐

  1. 以太坊智能合约编程之带菜鸟入门教程

    手把手带你走上智能合约编程之路 译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队.如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下角New ...

  2. 教程 | 以太坊智能合约编程之菜鸟教程

    教程 | 以太坊智能合约编程之菜鸟教程 译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队.如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下 ...

  3. 如何通过构建以太坊智能合约来销售商品

    如何通过构建以太坊智能合约来销售商品?这是个问题. 毫无疑问,比特币已经改变了我们看待和理解什么是金钱,价值以及最近由智能合约产生的所有权的方式.这很有趣,因为几乎每个人都听说过它或加密货币.来自许多 ...

  4. 以太坊智能合约安全入门了解一下(下)

    作者:RickGray 作者博客:http://rickgray.me/2018/05/26/ethereum-smart-contracts-vulnerabilities-review-part2 ...

  5. 以太坊智能合约安全入门了解一下(上)

    作者:RickGray 作者博客:http://rickgray.me/2018/05/17/ethereum-smart-contracts-vulnerabilites-review/ (注:本文 ...

  6. 【以太坊智能合约】Embark Framework 开发基础篇

    在之前的文章中,我们看到了使用Solidity开发以太坊智能合约的所有基本知识.我们使用了以太坊钱包,我们能够轻松设置小型产品开发环境.我们会发现开始的时候很不错,但是如果我们想要更深入的话呢?我们要 ...

  7. Python开发以太坊智能合约指南(web3.py)

    在以太坊上获得一个基本的智能合约是一个很简单的事,只需google查询"ERC20代币教程",你会发现有关如何做到这一点的大量信息.以编程方式与合约交互完全是另一回事,如果你是一个 ...

  8. 以太坊智能合约编程之菜鸟教程

    手把手带你走上智能合约编程之路 译注:原文首发于ConsenSys开发者博客,原作者为Eva以及ConsenSys的开发团队.如果您想要获取更多及时信息,可以访问ConsenSys首页点击左下角New ...

  9. 以太坊智能合约之如何执行智能合约?

    区块链技术在顶级技术中占据主导地位的主要原因在于其去中心化.虽然区块链的主要目的是在没有中心的情况下维护交易记录,但为了实现自动化,智能合约被引入.那么在写完智能合约之后呢?在本文的这个以太坊智能合约 ...

  10. 以太坊智能合约编程简单教程(全)

    有些人说以太坊太难对付,于是我们(译注:指Consensys, 下同)写了这篇文章来帮助大家学习如何利用以太坊编写智能合约和应用.这里所用到的工具,钱包,应用程序以及整个生态系统仍处于开发状态,它们将 ...

最新文章

  1. swift_042(Swift的typealias(别名)的用法)
  2. Ubuntu16.04中安装mininet
  3. github流程图_10月份Github上最热门的JavaScript开源项目
  4. 编写代码,实现一个栈(Stack)的类。
  5. git 冲突覆盖_git pull冲突解决之强制覆盖
  6. java 传址或传值
  7. 【渝粤教育】国家开放大学2018年秋季 1117t机电控制与可编程序控制 参考试题
  8. Unity笔记之凤凰模拟器
  9. 下载webex client的remover
  10. python蓝屏代码_死机、卡顿、蓝屏,Python部分的老江湖告诉我的一些超等反常代码...
  11. freebsd上运行hpool
  12. 怎样将jpg、png制作成windows桌面ico图标文件
  13. C++/MFC修行之路(6)停靠窗口
  14. python3安装库报错ERROR: Exception: Traceback (most recent call last): File “A:\ProgramData\Anacon
  15. Windows分盘,c盘已经满了,但d盘还有内存。
  16. chrome浏览器一键切换搜索引擎,一键切换谷歌和百度搜索(不需要重新输入keyword,带关键词切换引擎)
  17. 跨专业考浙大计算机考研难度,0基础跨专业计算机考研经验-2013浙大
  18. 当程序员后,才突然明白的21件事……
  19. STM32中断优先级概念
  20. 关于自己的一些想法-网络通用消费返点平台

热门文章

  1. HORNER(霍纳)法则的C实现以及算法比较 2.10
  2. 微信小程序第三方平台开发配置
  3. 读书笔记—颠覆式创新:移动互联网时代的生存法则
  4. IE浏览器日期转换问题
  5. 程序员的桌面画风竟然是酱紫的!
  6. barefoot公司和Tofino芯片
  7. Vue3.0项目——打造企业级音乐App(二)图片懒加载、v-loading指令的开发和优化
  8. 亚控科技的KingSCADA多个漏洞
  9. L1-009 N个数求和 (20 分)
  10. 中国大学MOOC中华茶礼仪真题及答案