这是 Solidity 教程系列文章第 8 篇介绍 Solidity API, 它们主要表现为内置的特殊的变量及函数, 存在于全局命名空间里
写在前面
Solidity 是以太坊智能合约编程语言, 阅读本文前, 你应该对以太坊智能合约有所了解,
如果你还不了解, 建议你先看以太坊是什么
欢迎订阅区块链技术专栏阅读更全面的分析文章
Solidity API 主要表现为 Solidity 内置的特殊的变量及函数, 他们存在于全局命名空间里, 主要分为以下几类:
1. 有关区块和交易的属性
2. 有关错误处理
3. 有关数学及加密功能
4. 地址相关
5. 合约相关
下面详细讲解下
区块和交易的属性(Block And Transaction Properties)
用来提供一些区块链当前的信息
block.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 开始所经过的秒数)
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.
错误处理
assert(bool condition)
用于判断内部错误, 条件不满足时抛出异常
require(bool condition):
用于判断输入或外部组件错误, 条件不满足时抛出异常
revert():
终止执行并还原改变的状态
数学及加密功能
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
- 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
- keccak256("ab", "c")
- keccak256("abc")
- keccak256(0x616263) // hex
- keccak256(6382179)
- keccak256(97, 98, 99) //ascii
地址相关
.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 的别名
另外, 当前合约里的所有函数均可支持调用, 包括当前函数本身
参考文档
Special Variables and Functions
深入浅出区块链 - 系统学习区块链, 打造最好的区块链技术博客
来源: http://geek.csdn.net/news/detail/256334