DTeam 团队日志

Doer、Delivery、Dream

面向老程序员的Solidity摘要

胡键 Posted at — Jul 16, 2018 阅读

开发以太坊DApp,Solidity是必经之路。然而,对于跟我一样的那些有多年开发经验的以太坊新人来讲,Solidity学习固然是一方面,但更重要的是快速了解它的惯例和套路,以及一些值得注意的事项。这,正是本文试图达到的目标。至于详尽的语法文档,还请各位自行查阅。

EVM和字节码

与Java代码类似,Solidity代码会先被编译成字节码,然后再由EVM负责执行。从逻辑上来讲,可以将以太坊视为一台计算机,其中的每个EVM节点类似在计算机中执行的进程,分布式账本则是这台计算机的存储。

一旦部署成功,其代码会被复制到以太坊上其他节点,并可以通过命令查看其源码。以Truffle开发环境为例:

  1. truffle develop
  2. 部署MyCoin合约,deploy
  3. MyCoin.at(地址),从其返回的json对象中的source属性即可看到合约代码。

合约部署之后就无法更新,这就给开发者带来了相当大的挑战:

执行代价

说到程序执行的代价,一般指的都是花多少内存、存储和CPU时间。但执行以太坊上的代码,除了这些通常意义的代价之外,还需要真金白银。这是因为以太坊上的交易确认都是需要花钱的!它们主要是那些改变以太坊状态的操作,如:

而且,与其他系统不同,这些操作的执行结果并不会立刻生效。它们会以交易的形式提交到交易池中等待矿工确认,这便是交易费的由来。并且,这个价格也不是一个固定值,它随着市场行情的波动上下浮动。如果你的交易长时间没有结果,那么可以看看是否是因为交易费过低。

关于交易费的行情,可以从最新的交易中了解。

这也给开发者带来了挑战:如何在实现功能的前提下尽可能的降低交易成本?

账户

要在以太坊上进行操作,必需要有以太坊账户。当前有两类账户类型:

这里也带来了一些关于安全性方面的概念转变:

合约语法

合约类似Java中的类,但与类不同之处在于,它的构造函数只会被调用一次,即部署合约的时候。

合约的状态变量相当于类的实例变量,但同样是持久化的。并且,mapping只能声明成状态变量但可在函数内引用。

变量类型同样也分值类型和引用类型,其中引用类型包括:数组和结构体,后者给自定义类型提供方案。

函数可以返回一个值或多个值,同时可以指定返回的变量。如:

function arithmetic(uint _a, uint _b)
    public
    pure
    returns (uint o_sum, uint o_product)
{
    o_sum = _a + _b;
    o_product = _a * _b;
}

函数修改器(Modifier)类似AOP中的拦截器,提供了修改函数执行流程的机会,一般用来做验证和检查。其中“_”用来将控制流返还给被修改的函数,如下例:

modifier onlySeller() { // Modifier
    require(
        msg.sender == seller,
        "Only seller can call this."
    );
    _;
}

function abort() public onlySeller { // Modifier usage
    // ...
}

几个重要的修改器:

事件提供了让外部应用了解合约状态变化的途径,一般使用流程是:

  1. 合约内部发出事件
  2. 外部应用利用web3监听事件

可见性:

合约支持多重继承。

EVM提供了4种数据位置用来存放数据:

规则:

由于合约执行是有成本的,需要警惕循环语句。

对于多重继承的合约,需要明确指明顺序,如:

contract X {}
contract A is X {}
contract C is A, X {}

fallback函数没有函数名,无法直接调用,但在两个情况下会被触发:

由于其无法被外部调用,EVM限制其只能最多消耗2300的gas,若超过,则fallback函数失败。因此,记得要测试合约的fallback函数是否会超过这个限制。

并且,fallback是安全事故的高发地,需要对其进行必要的安全相关的测试。

接口和抽象合约跟Java中的接口和抽象类差别不大,库(library)是一段可复用的代码,在调用它的合约上下文内执行:

合约抛出异常之后,状态回滚,当前有3种方式:

常见模式

鉴于以太坊应用的以下特点,编写solidity代码时需要非常小心:

常见的编码套路有:

最后,也是最省事的方式:使用成熟类库,如OpenZeppelin。关于Solidity的好东西,可以通过其Awesome List来了解。