这是一篇对以太坊智能合约与 Solidity 的一些简介,方便你们理解咱们这几期对合约安全性分析的文章。部份内容翻译自参考文献[1]安全
本质上,以太坊是一个去中心化的虚拟机,在运行的过程当中,能够按照必定顺序执行合约。合约由一组供用户调用的函数构成,好比说,一个标准的 ERC 20 合约应当实现如下六个函数。微信
当一个用户想将本身的 ERC 20 token 转给其余地址的时候,能够发起一笔交易来调用 transfer
函数,让以太坊执行合约中 transfer
函数对应的代码,从而完成转帐。ide
在以太坊中,用户能够经过发起交易实现 3 个功能:函数
建立新的智能合约区块链
执行合约中的函数ui
转帐 ether翻译
交易由矿工打包进区块,全部区块构成了一个链。这样全部的交易就有了一个执行的顺序,基于这个顺序,也能够定出每一个时刻的合约状态和交易余额。code
在以太坊中,合约以字节码的形式发布到区块链上,并在 EVM (Ethereum Virutal Machine) 中执行。在用户开发的时候,不须要直接编写字节码。以太坊社区提供了一套叫作 Solidity 的语言。一个由 Solidity 开发合约的代码以下图所示。orm
在合约的前两行,定义了一个变量和一个字典映射。在每次合约被执行的时候,这两个变量均可能被修改。当下一次合约被执行的时候,若是读取了这两个变量,获得的将是修改后的内容。cdn
合约的第一个函数 AWallet
与合约名相同,是这个合约的构造函数。当这个合约在区块链上被创造的时候,构造函数被执行,通常用于初始化合约中的一些变量。
在 Solidity 代码中,能够经过 msg.sender
和 msg.value
两个变量获取:1. 触发本次合约执行的交易是谁发的,2. 触发本次合约执行的交易向合约里转入了多少 ether。基于这两个变量,能够实现合约操做的权限管理,也能够实现将一些数字资产由用户私钥控制转为合约执行控制。
Solidity 容许异常的存在,例如函数 pay
的第一行,若是调用这个函数的地址与建立合约的地址不一致,则意味着调用合约的人没有动用合约里资产的权限,那么就经过 throw
触发了一个异常。当异常被触发时,没有任何捕获(catch)的方式,直接中止合约的执行,回滚状态,并扣除所有的交易费用。
对于类型为 address
的变量 r
, r.send(amount)
表示由合约向地址 v
发送数额为 amount
的 wei. (10^18 wei = 1 ether )
最后一个没有函数名的函数 function () 称为回退(fallback)函数,是智能合约中一个特殊的函数。由于 EVM 的字节码中并无对函数的支持,因此,Solidity 在将代码编译成字节码后,字节码的第一部分即是函数匹配。用户经过指定要调用函数的函数名和参数类型的哈希值的前四个字节来告诉 EVM 执行哪一个函数。例如 byte4(sha3("pay(uint,address)"))
,这四个字节被称为函数签名。若是用户调用时使用的函数签名匹配到了一个函数,则执行这个函数。若是没有匹配到任何函数,回退函数将做为 default 选项被执行。
在以太坊中,每次合约函数的调用须要被全部的矿工执行。交易中的交易费能够激励矿工们作这件事情,同时保护以太坊合约执行上免受 DoS 攻击(攻击者提交大量计算机很大的合约)。
执行交易费由燃料用量(gas used)和燃料费(gas price)决定。燃料用量由合约执行过程当中执行了的操做计算,EVM 虚拟机的每个字节码指令都标注了燃料用量。燃料费是用户的出价,更高的燃料费意味着交易能够更早被加入区块。燃料用量乘燃料费就是合约执行的交易费。
同时,每笔交易要指定燃料用量上限(gas limit)。燃料用量上限乘以燃料费是预付款。交易发起时要保证帐户余额中有足够的钱支付预付款。当燃料用到上限时,若是尚未执行结束,将判断为执行失败,回滚全部操做,并没收预付款。若是合约执行成功,预付款中未使用的部分会被退回。
参考文献: [1] Atzei, Nicola, Massimo Bartoletti, and Tiziana Cimoli. "A survey of attacks on ethereum smart contracts (sok)." Principles of Security and Trust. Springer, Berlin, Heidelberg, 2017. 164-186.
欢迎关注咱们的微信公众号:Conflux中文社区(Conflux-Chain)
添加微信群管理员 Confluxgroup 回复“加群”加入 Conflux官方交流群