Solidity 全局变量与函数
在全局命名空间上,存在许多特殊的变量及函数,这些函数多用做提供与区块链相关的信息。
区块与交易相关
block
block
包含了各种与当前或早前区块相关的信息
名称 | 类型 / 函数签名 | 说明 |
---|---|---|
block.blockhash | function (uint blockNumber) returns(bytes32) | 返回区块数为 blockNumber 的区块的哈希值。只能用于当前区块之前的 256 个区块,查询当前区块在内的其他区块都会返回 0。一定程度可以受到矿工的影响 |
block.coinbase | address | 挖出当前区块的矿工的地址 |
block.difficulty | uint | 当前区块的区块难度 |
block.gaslimit | uint | 所有交易在内,当前区块允许消耗的 gas 的最大数目 |
block.number | uint | 当前区块的区块数 |
block.timestamp now | uint | 当前区块的时间戳,一定程度可以受到矿工的影响 |
提示:
除非清楚在做什么,不要依靠
block.timestamp
、now
或者block.blockhash
作为随机数的来源。时间戳和区块的哈希都能在一定程度上受到矿工的影响。如果将这些作为随机数的来源,会有被不怀好意的矿工利用,"随机"出对他们更有利的结果。
以太坊规定当前区块的时间戳必须严格大于上一个区块的时间戳。但这只能保证当前区块的时间戳在社区中较权威的链中,大小在相邻的两个区块的时间戳之间。
提示:
出于规模的考虑,调用
block.blockhash
只能获取当前区块之外的最近的 256 个区块的哈希值。查询其他任何区块(包括当前区块)的哈希值都只会得到 0。
msg
msg
包含了各种与当前合约调用者所发消息有关的信息
名称 | 类型 / 函数签名 | 说明 |
---|---|---|
msg.data | bytes | 存放了完整的 calldata |
msg.gas | uint | gasleft 函数代替。 |
gasleft | function() returns(uint256) | 返回剩余可以使用的 gas |
msg.sender | address | (当前调用中)消息发送者的地址 |
msg.sig | bytes4 | calldata 的首四字节(即,函数的标识符) |
msg.value | uint | 消息中附带的 wei 的数量 |
提示:
msg
中的任何成员,包括msg.sender
、msg.value
随时都会因调用外部函数而改变,这也包括调用库中的函数。
tx
tx
包含了各种与当前交易相关的信息
名称 | 类型 / 函数签名 | 说明 |
---|---|---|
tx.gasprice | uint | 当前交易中的 gas 的价格 |
tx.origin | address | 当前交易发送者的地址(位于完整调用链的最顶层) |
错误处理
本书有专门的章节讲解 Solidity 的错误处理机制。在此,仅仅列出全局中用于处理错误的三个函数
函数 | 说明 |
---|---|
assert(bool condition) | 如果不符合 condition,抛出—用于处理内部错误。 调用 assert 不会归还调用者剩余的 gas |
require(bool condition) | 如果不符合 condition,抛出—用于处理在输入中或外部组件中的错误。调用 require 会归还调用者剩余的 gas |
revert() | 终止执行,撤销当前调用中的任何状态改变。调用 revert 会归还调用者剩余的 gas |
数学与密码学相关函数
函数 | 说明 |
---|---|
addmod(uint x, uint y, uint k) returns (uint) | 计算 (x + y) % k ,加法运算不会失去精度,也无需考虑溢出问题。Solidity 0.5.0 起,将会假设 k != 0 |
mulmod(uint x, uint y, uint k) returns (uint) | 计算 (x * y) % k ,乘法运算不会失去精度,$2^{256}$ 及以为的值无需考虑溢出。Solidity 0.5.0 起,将会假设 k != 0 |
keccak256(...) returns (bytes32) sha3(...) returns (bytes32) | 计算参数紧密打包后的 Ethereum-SHA-3 (Keccak-256) 哈希值 |
sha256(...) returns (bytes32) | 计算参数紧密打包后的 SHA-256 哈希值 |
ripemd160(...) returns (bytes20) | 计算参数紧密打包后的 RIPEMD-160 哈希值 |
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address) | 用椭圆曲线签名恢复与公钥相关联的地址。若遇到错误,则返回 0 |
在一些私有区块链上,调用 sha256
、 ripemd160
或 ecrecover
可能会遇到 Gas 不足 (Out-of-Gas) 的问题。出现此类问题是这些操作采用称为预编译合约的方式实现。这些合约只有在受到第一条消息后才会存在,而对不存在的合约发送消息有着更高昂的开销,因而出现 Gas 不足的错误。一种 workaround 是先向那些要用到的合约转一笔小钱(如 1 wei)。这类问题不会在以太坊官方及测试网络中出现。s
紧密打包 (tightly packed)
上表的"紧密打包"是指将各个参数紧密相连,没有填充。例如,以下语句都是相同的:
keccak256("Zz", "zz")
keccak256("Zzzz")
keccak256(0x5A7A7A7A)
keccak256(90, 122, 122)
如果需要填充,可以使用显式类型转换,例如: keccak256("\x00\x12")
等同于 keccak256(uint16(0x12))
。
此外,常量在打包时会使用最小可能的空间,因此, keccak256(0)
与 keccak256(uint8(0))
相等, keccak256(0x12345678)
与 keccak256(uint32(0x12345678))
相等。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Solidity 映射 Mapping
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论