了解了以太坊基本知识后,这一章我们会介绍以太坊智能合约的基本结构,编程语言Solidity 的基本知识,包括变量、函数、异常处理等方面,以及如何编写以太坊智能合约,对其进行编译和部署 。 本章具体将涉及以下具体内容:
首先,我们来回顾一下编写智能合约相关的流程 。 当开发者使用 Solidity 语言编写智能合约时,智能合约实际上就是由 Solidity 代码编译后的程序,也就是说,智能合约的编译环境就是 Solidity 的编译环境 。 而这段程序(智能合约)的执行环境就是 EVM 。
在以太坊中, Solidity 编写的智能合约经过编译后会生成一串十六进制字节码,创建后进行调用时,也需要将调用的函数( function)名称和参数转化成一串十六进制字节码写进交易中 。 当用户通过发起 eth_sendTransaction 或者 eth_call 创建或者调用智能合约时,就要在交易( Transaction )的 data 字段填入这个十六进制码 。
创建智能合约时, EVM 会将这段字节码解析成相应的指令符序列,存储到一个新建的智能合约地址下 。 当用户调用这个智能合约时,以太坊本身会根据交易里的 to 字段先获取到这个智能合约的信息, EVM 先根据 data 字段里解析出的具体函数和参数生成具体的指令,再依次执行这些指令得到执行结果,这些操作会涉及对账户状态数据进行更改 。
Solidity 编译器
以太坊官方社区提供了 Solidity 语言的编译开发工具 Solidity 项目( https://github.com/ethereum/solidity )。 该项目是用 C++编写的,使用者可以根据自己的操作系统下载相应发布版的二进制可执行文件 。 如果想使用最新的版本,可以同步最新的代码自行编译生成可执行文件 。
一个 Solidity 程序被编译器编译成十六进制字节码( EVM Code )后,下一步可以进行部署和测试 。 通常,先把智能合约部署到测试环境(测试链 https://testnet.etherscan.io/ 或者开发者自己搭建私有链)中进行测试,没有问题后才会发布到以太坊公有链 。 任何程序都有可能出现漏洞,未经测试的智能合约直接部署到以太坊公有链或者是其他生产环境的区块链上,后果都是严重的 。
以太坊官方社区还开发了 Solidity 智能合约的集成开发环境( IDE): Mix 和 Remix 。 不过 Mix 项目已经停止继续维护和开发 。 Remix (也叫 Browser-Solidity )是一个基于浏览器的 Solidity 编译器和集成开发环境,提供了交互式界面,以及编译、调用测试、发布等一系列功能,使用十分方便 。
5.2.1 Remix 界面
以太坊官方不仅提供了 Remix 的开源代码(https://github.com/ethereum/remix-ide),开发者可以同步代码到本地,搭建起自己的基于浏览器的 Solidity IDE,还提供了 Remix 的在线网站( http://remix.ethereum.org)。开发者甚至都不需要自己安装,直接在浏览器里访问网站,就可以进行开发、编译、调试、测试等工作 。 图 5-1 就是目前 Remix 最新版本的界面 。
5.2.2 初探 Remix 调试
5.2.3 使用 Remix 调试智能合约的多种调用方式
Truffle ( http://truffleframework.com)是现在比较流行的 Solidity 智能合约开发框架,功能十分强大,可以帮助开发者迅速搭建起一个 DApp。
Truffle 具体的特性有:
1 )内建智能合约编译、链接、部署和二进制包管理功能;
2 )支持对智能合约的自动测试;
3 )支持自动化部署、移植;
4 )支持公有链和私有链,可以轻松部署到不同的网络中;
5 )支持访问外部包,可以方便地基于 NPM 和 EthPM 引入其他智能合约的依赖;
6 )可以使用 Truffle 命令行工具执行外部脚本 。
下面大致讲解一些 Truffle 主要功能的使用。
5.3.1 Truffle 安装
Truffle 的安装十分方便 。 它是 JavaScript 编写的 Node.js 项目,使用包管理工具 NPM即可安装 。 在安装之前,你只需要准备好 Node.js 环境,官方推荐在使用 5.0 以上版本的Node.js 。
注意: 下面进行的所有操作,是在Ubuntu 18.04系统下进行的
安装Node.js:
sudo apt-get update
sudo apt-get install -y python-software-properties software-properties-common
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
安装包管理工具npm:
sudo apt install npm
安装Truffle:
sudo npm install -g truffle
这样你就能在命令行工具中使用 Truffle 命令了。
在开始使用 Truffle 新建一个项目之前,为了支持这个项目 的测试或者部署,还要进行一步操作 : 安装一个 Ethereum 客户端 。 为了提升测试效率,目前 Truffle 官方推出了 Ganache 作为测试的客户端 。 Ganache 的前身是 testrpc ,现在已经被整合到 Ganache 项目中。 Ganache 是一个本地内存执行的轻量级客户端,有良好的交互界面(见图 5-18 ) 。 它能做到对 Transaction 的 立即执行,因此使用者可以迅速地创建和调用自己编写的智能
合约 。
当用户基于 Ganache 进行充分的测试之后,可以通过一些官方或者非官方的客户端进行发布 。 比较常用的客户端有 Geth ( go-Ethereum )、Parity 、 Cpp-ethereum 等 。 只要用户将这些客户端相关信息添加进配置文件, Truffle 可以方便地通过指定客户端进行测试 。
安装ganache:
sudo npm install -g ganache-cli
5.3.2 创建
首先,新建一个文件夹作为项目工作空间,在这个目录中,执行 truffle init 命令:
y@ubuntu:~/truffleProjects/HelloWorld$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!
Commands:
Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test
这样,在当前目录下,会生成几个子目录:
先修改Truffle默认的配置文件truffle.js(参考:https://truffleframework.com/docs/truffle/reference/configuration ),
内容修改为:
module.exports = {
networks: {
development: {
host: "127.0.0.1",
port: 8545,
network_id: "*" // Match any network id
}
}
};
再在contracts目录下新建一个Greeter.sol智能合约
pragma solidity ^0.4.18;
contract Greeter
{
address public creator;
string public greeting;
constructor(string _greeting) public {
creator = msg.sender;
greeting = _greeting;
}
function greet() public constant returns (string)
{
return greeting;
}
function setGreeting(string _newgreeting) public
{
greeting = _newgreeting;
}
/**
Standard kill() function to recover funds
**/
function kill() public
{
// kills this contract and sends remaining funds back to creator
if(msg.sender == creator)
selfdestruct(creator);
}
}
然后在migrations目录下新建一个部署脚本文件:2_deploy_contracts.js,内容为:
var Greeter = artifacts.require("./Greeter.sol");
module.exports = function(deployer) {
deployer.deploy(Greeter, "Hello, World!"); //参数在第二个变量携带
};
5.3.3 编译
进入工程的./HelloWorld根目录下,执行truffle compile命令进行编译:
y@ubuntu:~/truffleProjects/HelloWorld/contracts$ truffle compile
Compiling ./contracts/Greeter.sol...
Writing artifacts to ./build/contracts
5.3.4 部署
如果没有启动ganache,则先执行 ganache-cli 启动以太坊客户端:
y@ubuntu:~/truffleProjects/HelloWorld$ ganache-cli
Ganache CLI v6.1.8 (ganache-core: 2.2.1)
Available Accounts
==================
(0) 0xd922d79a7a6b02149c72c1181f23b0c78b981dd7 (~100 ETH)
(1) 0xabed5bf28e087270b5e4065984b18a3a4d901ce3 (~100 ETH)
(2) 0xbd3311e62bd71ea69c1f895728ba63780efeec71 (~100 ETH)
(3) 0x25ebf2041ce9a418ed070f1b549dfc63915cacd9 (~100 ETH)
(4) 0x10a4d9692991961541794722a6ccd45436cfb758 (~100 ETH)
(5) 0x364b7749df3b92769c66bdb645e14d2cbd3efc18 (~100 ETH)
(6) 0x8b7d04ebcff49505e3e15f486bd30c149e263cd1 (~100 ETH)
(7) 0x0277152391ce9c2047510ce41c5aaf9f683ab6ef (~100 ETH)
(8) 0xd3fb464965e618fb3e59452e8aa64275d4626880 (~100 ETH)
(9) 0x0cae49341076ac515121332cc82de19c1be2ab30 (~100 ETH)
Private Keys
==================
(0) 0x5a3b367af6b4b6ee4d904537cf1b7af50fe7040bf9bcbb8f794fab26cf96cc0a
(1) 0x196b8cf10e6cab3dc50807927ab2d440dcea9ab3dc596107e2e3e2b026902783
(2) 0x1da4be27fab9f4d31b45040942a11ac23e2c3ccd5d87f3ce4067468776e81673
(3) 0x5389eb7191ab3c7262ce2c7c7915da10af7acdb8c096384f8f9e9ed5120cf471
(4) 0x1a7adf0d6f9acfb37374dfe58a06c2197b327bf028f5b15394a31dee658511da
(5) 0xe387bb77dcd18ae8bdb90080ec214da1763b8495e599b9b829f7d5040cb46d63
(6) 0xb0deb3c13fc9e6846b11f379e6aa7c55c978e36bf1b54df2fb299f8ef6cb742b
(7) 0xacc30cf870946956921fd1f0eed726d31643c968996a08f0a57ce02fcc6da890
(8) 0x1a50bd5f1a640a3711c04fb7eec86c7c60347649539d0d149110e99491664e43
(9) 0x82f2a36046953065d9e384725ddbf4fb8cbb4ad5841fa6f06a0289f5e006b617
HD Wallet
==================
Mnemonic: ocean almost silk laugh rebel argue daring armed sing comfort turtle rally
Base HD Path: m/44'/60'/0'/0/{account_index}
Gas Price
==================
20000000000
Gas Limit
==================
6721975
Listening on 127.0.0.1:8545
再打开一个新的终端,执行truffle migrate命令部署智能合约:
y@ubuntu:~/truffleProjects/Helloworld$ truffle migrate
Using network 'development'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x24f4e525c752ba7b4d597c05e81e3a62c09df6fb2cd85a2bacc5febbf454be70
Migrations: 0x323df10d38f4ec11e5665aa8f05fafeb138c2d95
Saving successful migration to network...
... 0xb548eae24919ce9fdfa1c4b83380cf64417d9a5b7056a9e8fcff17947ce89da6
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying Greeter...
... 0x063db93f60eefdab53842fcb5f798fe179352c1066676851c697af45768860ba
Greeter: 0x98c8360f4e2e66c7e03264465afa1ed1616ab4d8
Saving successful migration to network...
... 0x4670f90847091e7ae89bb61904701b975435b68313b3178a3ba2fd82efd10133
Saving artifacts...
上面的这一行:
Greeter: 0x98c8360f4e2e66c7e03264465afa1ed1616ab4d8
中的 Greeter后面的 0x98c8360f4e2e66c7e03264465afa1ed1616ab4d8 就是合约的部署地址,后面调用该智能合约时会用到。当然在/home/y/truffleProjects/Helloworld/build/contracts/Greeter.json文件中也可以看到合约信息,包括部署地址。
5.3.5 测试
Truffle提供了一种通过交互式控制台与智能合约进行交互的方式。
执行命令truffle console 进入控制台,再输入智能合约名称Greeter,可以查看智能合约的各个属性内容:
y@ubuntu:~/truffleProjects/Helloworld$ truffle console
truffle(development)> Greeter
{ [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: { get: [Function: get], set: [Function: set] },
contractName: { get: [Function: get], set: [Function: set] },
abi: { get: [Function: get], set: [Function: set] },
network: [Function: network],
networks: [Function: networks],
address: { get: [Function: get], set: [Function: set] },
transactionHash: { get: [Function: get], set: [Function: set] },
links: [Function: links],
events: [Function: events],
binary: [Function: binary],
deployedBinary: [Function: deployedBinary],
unlinked_binary: { get: [Function: get], set: [Function: set] },
bytecode: { get: [Function: get], set: [Function: set] },
deployedBytecode: { get: [Function: get], set: [Function: set] },
sourceMap: { get: [Function: get], set: [Function: set] },
deployedSourceMap: { get: [Function: get], set: [Function: set] },
source: { get: [Function: get], set: [Function: set] },
sourcePath: { get: [Function: get], set: [Function: set] },
legacyAST: { get: [Function: get], set: [Function: set] },
ast: { get: [Function: get], set: [Function: set] },
compiler: { get: [Function: get], set: [Function: set] },
schema_version: [Function: schema_version],
schemaVersion: [Function: schemaVersion],
updated_at: [Function: updated_at],
updatedAt: [Function: updatedAt] },
_property_values: {},
_json:
{ contractName: 'Greeter',
abi: [ [Object], [Object], [Object], [Object], [Object], [Object] ],
bytecode: '0x608060405234801561001057600080fd5b5060405161068e38038061068e83398101806040528101908080518201929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060019080519060200190610089929190610090565b5050610135565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d157805160ff19168380011785556100ff565b828001600101855582156100ff579182015b828111156100fe5782518255916020019190600101906100e3565b5b50905061010c9190610110565b5090565b61013291905b8082111561012e576000816000905550600101610116565b5090565b90565b61054a806101446000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806302d05d3f1461007257806341c0e1b5146100c9578063a4136862146100e0578063cfae321714610149578063ef690cc0146101d9575b600080fd5b34801561007e57600080fd5b50610087610269565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100d557600080fd5b506100de61028e565b005b3480156100ec57600080fd5b50610147600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061031f565b005b34801561015557600080fd5b5061015e610339565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561019e578082015181840152602081019050610183565b50505050905090810190601f1680156101cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101e557600080fd5b506101ee6103db565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561022e578082015181840152602081019050610213565b50505050905090810190601f16801561025b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561031d576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b565b8060019080519060200190610335929190610479565b5050565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103d15780601f106103a6576101008083540402835291602001916103d1565b820191906000526020600020905b8154815290600101906020018083116103b457829003601f168201915b5050505050905090565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106104ba57805160ff19168380011785556104e8565b828001600101855582156104e8579182015b828111156104e75782518255916020019190600101906104cc565b5b5090506104f591906104f9565b5090565b61051b91905b808211156105175760008160009055506001016104ff565b5090565b905600a165627a7a723058209e63676a8515a258bd5549bbb363406420a9905074df47bf38f7ecd367a0ebff0029',
deployedBytecode: '0x60806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806302d05d3f1461007257806341c0e1b5146100c9578063a4136862146100e0578063cfae321714610149578063ef690cc0146101d9575b600080fd5b34801561007e57600080fd5b50610087610269565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100d557600080fd5b506100de61028e565b005b3480156100ec57600080fd5b50610147600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061031f565b005b34801561015557600080fd5b5061015e610339565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561019e578082015181840152602081019050610183565b50505050905090810190601f1680156101cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101e557600080fd5b506101ee6103db565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561022e578082015181840152602081019050610213565b50505050905090810190601f16801561025b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561031d576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b565b8060019080519060200190610335929190610479565b5050565b606060018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103d15780601f106103a6576101008083540402835291602001916103d1565b820191906000526020600020905b8154815290600101906020018083116103b457829003601f168201915b5050505050905090565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106104ba57805160ff19168380011785556104e8565b828001600101855582156104e8579182015b828111156104e75782518255916020019190600101906104cc565b5b5090506104f591906104f9565b5090565b61051b91905b808211156105175760008160009055506001016104ff565b5090565b905600a165627a7a723058209e63676a8515a258bd5549bbb363406420a9905074df47bf38f7ecd367a0ebff0029',
sourceMap: '26:595:0:-;;;106:101;8:9:-1;5:2;;;30:1;27;20:12;5:2;106:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;160:10;150:7;;:20;;;;;;;;;;;;;;;;;;191:9;180:8;:20;;;;;;;;;;;;:::i;:::-;;106:101;26:595;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;',
deployedSourceMap: '26:595:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:22;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;456:162;;8:9:-1;5:2;;;30:1;27;20:12;5:2;456:162:0;;;;;;298:87;;8:9:-1;5:2;;;30:1;27;20:12;5:2;298:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;213:79;;8:9:-1;5:2;;;30:1;27;20:12;5:2;213:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;213:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77:22;;8:9:-1;5:2;;;30:1;27;20:12;5:2;77:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;77:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49;;;;;;;;;;;;;:::o;456:162::-;569:7;;;;;;;;;;;555:21;;:10;:21;;;552:59;;;603:7;;;;;;;;;;;590:21;;;552:59;456:162::o;298:87::-;365:12;354:8;:23;;;;;;;;;;;;:::i;:::-;;298:87;:::o;213:79::-;255:6;277:8;270:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;213:79;:::o;77:22::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;26:595::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o',
source: 'pragma solidity ^0.4.18;\n\ncontract Greeter\n{\n address public creator;\n string public greeting;\n\n constructor(string _greeting) public {\n \tcreator = msg.sender;\n greeting = _greeting;\n }\n\n function greet() public constant returns (string)\n {\n\treturn greeting;\n }\n\n function setGreeting(string _newgreeting) public\n {\n\tgreeting = _newgreeting;\t\n }\n \n /**\n\tStandard kill() function to recover funds\n **/\n function kill() public\n {\n\t// kills this contract and sends remaining funds back to creator\n\tif(msg.sender == creator)\n selfdestruct(creator);\n }\n\n}\n',
sourcePath: '/home/y/truffleProjects/Helloworld/contracts/Greeter.sol',
ast:
{ absolutePath: '/home/y/truffleProjects/Helloworld/contracts/Greeter.sol',
exportedSymbols: [Object],
id: 53,
nodeType: 'SourceUnit',
nodes: [Array],
src: '0:622:0' },
legacyAST:
{ absolutePath: '/home/y/truffleProjects/Helloworld/contracts/Greeter.sol',
exportedSymbols: [Object],
id: 53,
nodeType: 'SourceUnit',
nodes: [Array],
src: '0:622:0' },
compiler:
{ name: 'solc',
version: '0.4.24+commit.e67f0147.Emscripten.clang' },
networks: { '1539915801151': [Object] },
schemaVersion: '2.0.1',
updatedAt: '2018-10-19T02:38:27.423Z' },
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 { provider: [Object], polls: {}, timeout: null },
currentProvider: Provider { provider: [Object] },
eth:
Eth {
_requestManager: [Object],
getBalance: [Object],
getStorageAt: [Object],
getCode: [Object],
getBlock: [Object],
getUncle: [Object],
getCompilers: [Object],
getBlockTransactionCount: [Object],
getBlockUncleCount: [Object],
getTransaction: [Object],
getTransactionFromBlock: [Object],
getTransactionReceipt: [Object],
getTransactionCount: [Object],
call: [Object],
estimateGas: [Object],
sendRawTransaction: [Object],
signTransaction: [Object],
sendTransaction: [Object],
sign: [Object],
compile: [Object],
submitWork: [Object],
getWork: [Object],
coinbase: [Getter],
getCoinbase: [Object],
mining: [Getter],
getMining: [Object],
hashrate: [Getter],
getHashrate: [Object],
syncing: [Getter],
getSyncing: [Object],
gasPrice: [Getter],
getGasPrice: [Object],
accounts: [Getter],
getAccounts: [Object],
blockNumber: [Getter],
getBlockNumber: [Object],
protocolVersion: [Getter],
getProtocolVersion: [Object],
iban: [Object],
sendIBANTransaction: [Function: bound transfer] },
db:
DB {
_requestManager: [Object],
putString: [Object],
getString: [Object],
putHex: [Object],
getHex: [Object] },
shh:
Shh {
_requestManager: [Object],
version: [Object],
info: [Object],
setMaxMessageSize: [Object],
setMinPoW: [Object],
markTrustedPeer: [Object],
newKeyPair: [Object],
addPrivateKey: [Object],
deleteKeyPair: [Object],
hasKeyPair: [Object],
getPublicKey: [Object],
getPrivateKey: [Object],
newSymKey: [Object],
addSymKey: [Object],
generateSymKeyFromPassword: [Object],
hasSymKey: [Object],
getSymKey: [Object],
deleteSymKey: [Object],
post: [Object] },
net:
Net {
_requestManager: [Object],
listening: [Getter],
getListening: [Object],
peerCount: [Getter],
getPeerCount: [Object] },
personal:
Personal {
_requestManager: [Object],
newAccount: [Object],
importRawKey: [Object],
unlockAccount: [Object],
ecRecover: [Object],
sign: [Object],
sendTransaction: [Object],
lockAccount: [Object],
listAccounts: [Getter],
getListAccounts: [Object] },
bzz:
Swarm {
_requestManager: [Object],
blockNetworkRead: [Object],
syncEnabled: [Object],
swapEnabled: [Object],
download: [Object],
upload: [Object],
retrieve: [Object],
store: [Object],
get: [Object],
put: [Object],
modify: [Object],
hive: [Getter],
getHive: [Object],
info: [Getter],
getInfo: [Object] },
settings: Settings { defaultBlock: 'latest', defaultAccount: undefined },
version:
{ api: '0.20.6',
node: [Getter],
getNode: [Object],
network: [Getter],
getNetwork: [Object],
ethereum: [Getter],
getEthereum: [Object],
whisper: [Getter],
getWhisper: [Object] },
providers:
{ HttpProvider: [Function: HttpProvider],
IpcProvider: [Function: IpcProvider] },
_extend:
{ [Function: ex]
formatters: [Object],
utils: [Object],
Method: [Function: Method],
Property: [Function: Property] } },
class_defaults:
{ from: '0xd922d79a7a6b02149c72c1181f23b0c78b981dd7',
gas: 6721975,
gasPrice: 100000000000 },
currentProvider:
HttpProvider {
host: 'http://127.0.0.1:8545',
timeout: 0,
user: undefined,
password: undefined,
headers: undefined,
send: [Function],
sendAsync: [Function],
_alreadyWrapped: true },
network_id: '1539915801151' }
执行调用Greeter智能合约的命令:
Greeter.at(“address”).greet.call()
当然本例的合约部署地址是:
0x98c8360f4e2e66c7e03264465afa1ed1616ab4d8
所以执行:
truffle(development)> Greeter.at("0x98c8360f4e2e66c7e03264465afa1ed1616ab4d8").greet.call()
'Hello, World!'
可以看到输出结果是: ‘Hello, World!’,这就是部署Greeter合约时,参数"Hello, World!"
注意:上述创建、编译、部署、测试过程也参考了区块链(九)用Truffle框架运行一个“Hello World!”智能合约
本章主要介绍了使用 Solidity 语言开发智能合约的工具,包括编译工具 Solc 、集成开发环境 Remix 、 DApp 开发框架 Truffle ,以及编写智能合约的安全性问题和建议 。 虽然以太坊和 Solidity 项目从诞生到现在只有三四年的时间,而且项目的鲁棒性和性能还有待提升,但是其相关的开发工具已经较为完善,通过学习这些工具的使用,用户能更高效地进行智能合约和 DApp 的开发 。 同时在编写智能合约过程中,开发者还应根据 Solidity 和 EVM 的特性,着重注意智能合约的安全性,防止可能漏洞发生 。