智能合约语言Solidity Solidity API

链客,专为开发者而生,有问必答!javascript

此文章来自链客区块链技术问答社区,未经容许拒绝转载。java

图片描述

Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,若是你还不了解,建议你先看以太坊是什么?web

Solidity API 主要表现为Solidity 内置的特殊的变量及函数,他们存在于全局命名空间里,主要分为如下几类:编程

有关区块和交易的属性安全

ABI编码函数编程语言

有关错误处理ide

有关数学及加密功能函数

地址相关区块链

合约相关测试

下面详细讲解下

区块和交易的属性(Block And Transaction Properties)

用来提供一些区块链当前的信息。

blockhash(uint blockNumber) returns (bytes32):返回给定区块号的哈希值,只支持最近256个区块,且不包含当前区块。

block.coinbase (address): 当前块矿工的地址。

block.difficulty (uint):当前块的难度。

block.gaslimit (uint):当前块的gaslimit。

block.number (uint):当前区块的块号。

block.timestamp (uint): 当前块的Unix时间戳(从1970/1/1 00:00:00 UTC开始所通过的秒数)

gasleft() (uint256): 获取剩余gas。

msg.data (bytes): 完整的调用数据(calldata)。

msg.gas (uint): 当前还剩的gas(弃用)。

msg.sender (address): 当前调用发起人的地址。

msg.sig (bytes4):调用数据(calldata)的前四个字节(例如为:函数标识符)。

msg.value (uint): 这个消息所附带的以太币,单位为wei。

now (uint): 当前块的时间戳(block.timestamp的别名)

tx.gasprice (uint) : 交易的gas价格。

tx.origin (address): 交易的发送者(全调用链)

注意:msg的全部成员值,如msg.sender,msg.value的值能够由于每一次外部函数调用,或库函数调用发生变化(由于msg就是和调用相关的全局变量)。

不该该依据block.timestamp, now 和 block.blockhash来产生一个随机数(除非你确实须要这样作),这几个值在必定程度上被矿工影响(好比在赌博合约里,不诚实的矿工可能会重试去选择一个对本身有利的hash)。

对于同一个链上连续的区块来讲,当前区块的时间戳(timestamp)老是会大于上一个区块的时间戳。

为了可扩展性的缘由,你只能查最近256个块,全部其它的将返回0.

ABI编码函数

Solidity 提供了一下函数,用来直接获得ABI编码信息,这些函数有:

  • abi.encode(...) returns (bytes):计算参数的ABI编码。
  • abi.encodePacked(...) returns (bytes):计算参数的紧密打包编码
  • abi. encodeWithSelector(bytes4 selector, ...) returns (bytes): 计算函数选择器和参数的ABI编码
  • abi.encodeWithSignature(string signature, ...) returns (bytes): 等价于* abi.encodeWithSelector(bytes4(keccak256(signature), ...)

经过ABI编码函数能够在不用调用函数的状况下,得到ABI编码值,下面经过一段代码来看看这些方式的使用:

pragma solidity ^0.4.24;contract testABI { function abiEncode() public constant returns (bytes) { abi.encode(1); // 计算 1 的ABI编码 return abi.encodeWithSignature("set(uint256)", 1); //计算函数set(uint256) 及参数1 的ABI 编码 }}

错误处理

assert(bool condition)用于判断内部错误,条件不知足时抛出异常

require(bool condition):用于判断输入或外部组件错误,条件不知足时抛出异常

require(bool condition, string message)同上,多了一个错误信息。

revert():终止执行并还原改变的状态

revert(string reason)同上,提供一个错误信息。

以前老的错误处理方式用throw 及 if … throw,这种方式会消耗掉全部剩余的gas。目前throw 的方式已经被弃用。

数学及加密功能

addmod(uint x, uint y, uint k) returns (uint):计算(x + y) % k,加法支持任意的精度且不会在2**256处溢出,从0.5.0版本开始断言k != 0。

mulmod(uint x, uint y, uint k) returns (uint):计算(x y) % k, 乘法支持任意的精度且不会在2*256处溢出, 从0.5.0版本开始断言k != 0。

keccak256(…) returns (bytes32):使用以太坊的(Keccak-256)计算HASH值。紧密打包参数。

sha256(…) returns (bytes32):使用SHA-256计算hash值,紧密打包参数。

sha3(…) returns (bytes32):keccak256的别名

ripemd160(…) returns (bytes20):使用RIPEMD-160计算HASH值。紧密打包参数。

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):经过椭圆曲线签名来恢复与公钥关联的地址,或者在错误时返回零。可用于签名数据的校验,若是返回结果是签名者的公匙地址,那么说明数据是正确的。

ecrecover函数须要四个参数,须要被签名数据的哈希结果值,r,s,v分别来自签名结果串。r = signature[0:64]s = signature[64:128]v = signature[128:130]其中v取出来的值或者是00或01。要使用时,咱们先要将其转为整型,再加上27,因此咱们将获得27或28。在调用函数时v将填入27或28。

用javascript表达以下:

var msg = '0x8CbaC5e4d803bE2A3A5cd3DbE7174504c6DD0c1C'var hash = web3.sha3(msg)var sig = web3.eth.sign(address, h).slice(2)var r = 0x${sig.slice(0, 64)}var s = 0x${sig.slice(64, 128)}var v = web3.toDecimal(sig.slice(128, 130)) + 27

紧密打包参数(tightly packed)意思是说参数不会补位,是直接链接在一块儿的,下面几个是相等的。

keccak256("ab", "c")keccak256("abc")keccak256(0x616263) // hexkeccak256(6382179)keccak256(97, 98, 99) //ascii

若是须要填充,能够使用显式类型转换:keccak256(“x00x12”) 与keccak256(uint16(0x12))相同。

注意,常量将使用存储它们所需的最少字节数来打包,例如keccak256(0) == keccak256(uint8(0))和keccak256(0x12345678) == keccak256(uint32(0x12345678))

在私链(private blockchain)上运行sha256,ripemd160或ecrecover可能会出现Out-Of-Gas报错。由于私链实现了一种预编译合约,合约要在收到第一个消息后才会真正存在(虽然他们的合约代码是硬编码的)。而向一个不存在的合约发送消息,因此才会致使Out-Of-Gas的问题。一种解决办法(workaround)是每一个在你真正使用它们以前先发送1 wei到这些合约上来完成初始化。在官方和测试链上没有这个问题。

地址相关

.balance (uint256):Address的余额,以wei为单位。

.transfer(uint256 amount):发送给定数量的ether到某个地址,以wei为单位。失败时抛出异常。

.send(uint256 amount) returns (bool):发送给定数量的ether到某个地址,以wei为单位, 失败时返回false。

.call(…) returns (bool):发起底层的call调用。失败时返回false。

.callcode(…) returns (bool):发起底层的callcode调用,失败时返回false。不鼓励使用,将来可能会移除。

.delegatecall(…) returns (bool):发起底层的delegatecall调用,失败时返回false

更多信息参考地址篇。

警告:send() 执行有一些风险:若是调用栈的深度超过1024或gas耗光,交易都会失败。所以,为了保证安全,必须检查send的返回值,若是交易失败,会回退以太币。若是用transfer会更好。

合约相关

this(当前合约的类型):表示当前合约,能够显式的转换为Address

selfdestruct(address recipient):销毁当前合约,并把它全部资金发送到给定的地址。

suicide(address recipient):selfdestruct的别名

另外,当前合约里的全部函数都可支持调用,包括当前函数自己。

相关文章
相关标签/搜索