以太坊社区开发并开源了非常好用的在线 Solidity 集成开发环境Remix,可以方便的在 Remix 中编写、部署、测试智能合约,Remix 提供了强大的自动完成,语法高亮,实时编译检查错误等。打开remix,界面如下:
在代码区输入一下合约代码:
pragma solidity ^0.4.21;
contract Phone {
string public model;
int64 price;
function Phone (string initalModel, int64 initalPrice) public {
model = initalModel;
price = initalPrice;
}
function setModel(string newModel) public {
model = newModel;
}
function getModel() public view returns (string) {
return model;
}
}
以太坊上写智能合约,只要是用到了Solidity语言。Solidity官方文档如是说:
Solidity is a contract-oriented, high-level language for implementing smart contracts. It was influenced by C++, Python and JavaScript and is designed to target the Ethereum Virtual Machine (EVM).
翻译为中文就是:Solidity是面向合约的高级智能合约编程语言,其设计受到了 C++、Python、Javascript 语言的影响,运行环境是以太坊虚拟机(EVM)。
Solidity 属于强类型语言,内含的类型除了常见编程语言中的标准类型,还包括 address 等以太坊独有的类型,Solidity 源码文件通常以 .sol 作为扩展名。
通过solidity在代码区写好了代码之后,就可以进行部署了。
接下来看看在remix中合约是如何部署,运行的。
首先是要编译,点击Compile下的“Start to compile”按钮。如果选择了“Auto compile”,就会自动编译,不需要这部操作。
如果程序编译出错,会直接在编译区抛出异常,如果无误,就会显示如上图的绿色区域。
然后切换到Run,remix会自动识别出要部署的合约实例。
部署智能合约时,需要注意的是:
部署完成之后,就会显示出可被调用的合约方法:
可以看出程序中只有setModel和getModel方法,但是部署之后却多了一个model方法(但是没有price方法)。这就是 Solidity 为public类型的存储型变量生成的 getter 方法,实际上如果一个存储变量类型为public,就不需要手动为它写一个get方法了。
Solidity源代码要成为可以运行在以太坊上的智能合约需要经历如下的步骤:
而使用Javascript编写的DApp通常通过web3.js + ABI去调用智能合约中的函数来实现数据的读取和修改。整个过程可以用下图示意:
Bytecode和ABI可以认为是智能合约源代码的两种外在表现形式,其中Bytecode是给机器执行的,而ABI是给 DApp 开发者用的用自然语言描述的合约接口规范。
简单地将,智能合约可以理解为把“合同”变为代码,然后编译成Bytecode和ABI,Bytecode用来部署,ABI用来调用。
通过在remix的log区域,可以看出部署的整个流程,当点击Deploy后,查看log:
合约部署实际上是发起了1笔交易,交易的接收者为空,以太坊将接收者为空的交易默认为是合约实例创建请求,这类交易中会携带当前部署合约的机器码(ByteCode),部署成功的话会返回新建的合约账户,合约部署本身需要消耗 Gas,这个费用是发起者支付的。
此外,可以看到交易中携带的合约机器码(bytecode)是十六进制串,这个可读性是很差的。如果想查看某个合约编译后的机器码,可以直接在 Compile 目录下点击 Details 按钮,如下图:
合约部署的直观结果是我们得到了一个账户,但是我们仅仅有这个账户的地址,而没有账户的公钥、私钥,这就是合约定义:contract instance is an account controlled by code 的准确含义,后续和合约的交互也只能通过代码,即智能合约的函数调用。
在Remix上部署、测试智能合约,不论是call还是transaction,速度都非常快,这是因为测试时以太坊网络运行在内存中,并且是单节点,速度自然很快,但是缺陷是每次页面加载,这个测试网络中的合约实例、合约中的数据都会丢失,网络中的账户及余额也会重建。
然而实际的以太坊网络,不论是测试网络还是主网,都不会这么快,在分布式网络上达成共识确实是个很复杂的过程,尤其是对于目前使用 POW 共识算法的以太坊来说。
前端工程师修改页面源代码后需要刷新浏览器,才能看到最新的页面效果,如果智能合约的源代码被修改,我们同样需要重新部署智能合约的示例,并测试这个全新的合约实例。与前端页面开发不同的是,刷新浏览器之后,老的页面的各种样式、DOM接口、应用状态都被销毁了,而以太坊上老的合约实例是不会被销毁的,即使部署了新的版本,如果你愿意也能和老版本继续交互。