🐰5 内置函数

[TOC]

内置函数

在全局命名空间中已经预设了一些特殊的变量和函数,他们主要用来提供关于区块链的信息或一些通用的工具函数。

区块和交易属性

函数
说明

blockhash(uint blockNumber) returns (bytes32)

最近的 256 个区块且不包括当前区块的区块哈希

block.chainid (uint)

当前链 id

block.coinbase ( address )

挖出当前区块的矿工地址

block.difficulty ( uint )

当前区块难度

block.gaslimit ( uint )

当前区块 gas 限额

block.number ( uint )

当前区块号

block.timestamp ( uint)

自 unix epoch 起始当前区块以秒计的时间戳

gasleft() returns (uint256)

剩余的 gas

msg.data ( bytes )

完整的 calldata

msg.sender ( address )

消息发送者(当前调用)

msg.sig ( bytes4 )

calldata 的前 4 字节(也就是函数标识符)

msg.value ( uint )

随消息发送的 wei 的数量

tx.gasprice (uint)

交易的 gas 价格

tx.origin (address payable)

交易发起者(完全的调用链)

  • block.blockhash() 已弃用,直接使用 blockhash()。

ABI 编码及解码函数

ABI 编码及解码函数

abi.decode(bytes memory encodedData, (...)) returns (...)

  • 对给定的数据进行ABI解码,而数据的类型在括号中第二个参数给出 。 例如: (uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes)) abi.encode(...) returns (bytes): ABI - 对给定参数进行编码

abi.encodePacked(...) returns (bytes)

  • 对给定参数执行 紧打包编码 ,注意,可以不明确打包编码。

abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)

  • ABI - 对给定第二个开始的参数进行编码,并以给定的函数选择器作为起始的 4 字节数据一起返回

abi.encodeWithSignature(string signature, ...) returns (bytes)

  • 等价于 abi.encodeWithSelector(bytes4(keccak256(signature), ...)

编码函数可以用于构造函数调用数据,而不用进行实际的调用。此外,keccak256(abi.encodePacked(a, b)) 是一种计算结构化数据的哈希值(使用不同的函数参数类型也有可能会引起“哈希冲突” )的方式,不推荐使用的 keccak256(a, b) 。

错误处理

错误处理

assert(bool condition)

  • 如果不满足条件,则会导致Panic 错误,则撤销状态更改 - 用于检查内部错误。

require(bool condition)

  • 如果条件不满足则撤销状态更改 - 用于检查由输入或者外部组件引起的错误。

require(bool condition, string memory message)

  • 如果条件不满足则撤销状态更改 - 用于检查由输入或者外部组件引起的错误,可以同时提供一个错误消息。

revert()

  • 终止运行并撤销状态更改。

revert(string memory reason)

  • 终止运行并撤销状态更改,可以同时提供一个解释性的字符串。

数学和密码学函数

数学和密码学函数

addmod(uint x, uint y, uint k) returns (uint)

  • 计算 (x + y) % k,加法会在任意精度下执行,并且加法的结果即使超过 2**256 也不会被截取。从 0.5.0 版本的编译器开始会加入对 k != 0 的校验(assert)。

mulmod(uint x, uint y, uint k) returns (uint)

  • 计算 (x * y) % k,乘法会在任意精度下执行,并且乘法的结果即使超过 2**256 也不会被截取。从 0.5.0 版本的编译器开始会加入对 k != 0 的校验(assert)。

keccak256((bytes memory) returns (bytes32)

  • 计算 Keccak-256 哈希。

sha256(bytes memory) returns (bytes32)

  • 计算参数的 SHA-256 哈希。

ripemd160(bytes memory) returns (bytes20)

  • 计算参数的 RIPEMD-160 哈希。

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)

  • 利用椭圆曲线签名恢复与公钥相关的地址,错误返回零值。

地址成员 address

<address>.balance (uint256)

  • 以 Wei 为单位的 地址类型 Address 的余额。

  • 在版本0.5.0之前,Solidity允许通过合约实例来访问地址的成员,例如 this.balance ,不过现在禁止这样做,必须显式转换为地址后访问,如: address(this).balance 。

<address>.code (bytes memory)

  • 在地址类型 Address 上的代码(可以为空)

<address>.codehash (bytes32)

  • ref:address的codehash

<address payable>.transfer(uint256 amount)

  • 向 地址类型 Address 发送数量为 amount 的 Wei,失败时抛出异常,使用固定(不可调节)的 2300 gas 的矿工费。

<address payable>.send(uint256 amount) returns (bool)

  • 向 地址类型 Address 发送数量为 amount 的 Wei,失败时返回 false,发送 2300 gas 的矿工费用,不可调节。

  • 使用 send 有很多危险:如果调用栈深度已经达到 1024(这总是可以由调用者所强制指定),转账会失败;并且如果接收者用光了 gas,转账同样会失败。为了保证以太币转账安全,总是检查 send 的返回值,利用 transfer 或者下面更好的方式: 用这种接收者取回钱的模式。

<address>.call(bytes memory) returns (bool, bytes memory)

  • 用给定的有效载荷(payload)发出低级 CALL 调用,返回成功状态及返回数据,发送所有可用 gas,也可以调节 gas。

  • 在执行另一个合约函数时,应该尽可能避免使用 .call() ,因为它绕过了类型检查,函数存在检查和参数打包。

<address>.delegatecall(bytes memory) returns (bool, bytes memory)

  • 用给定的有效载荷 发出低级 DELEGATECALL 调用 ,返回成功状态并返回数据,发送所有可用 gas,也可以调节 gas。 发出低级函数 DELEGATECALL,失败时返回 false,发送所有可用 gas,可调节。

  • 如果在通过低级函数 delegatecall 发起调用时需要访问存储中的变量,那么这两个合约的存储布局需要一致,以便被调用的合约代码可以正确地通过变量名访问合约的存储变量。 这不是指在库函数调用(高级的调用方式)时所传递的存储变量指针需要满足那样情况。

<address>.staticcall(bytes memory) returns (bool, bytes memory)

  • 用给定的有效载荷 发出低级 STATICCALL 调用,返回成功状态并返回数据,发送所有可用 gas,也可以调节 gas。

类型信息

表达式 type(X) 可用于检索参数 X 的类型信息(仅能是合约和整型)。

type(C).name

  • 获得合约名

type(C).creationCode

  • 获得包含创建合同字节码的内存字节数组。它可以在内联汇编中构建自定义创建例程,尤其是使用 create2 操作码。 不能在合同本身或派生的合同访问此属性。 因为会引起循环引用。

type(C).runtimeCode

  • 获得合同的运行时字节码的内存字节数组。这是通常由 C 的构造函数部署的代码。 如果 C 有一个使用内联汇编的构造函数,那么可能与实际部署的字节码不同。 还要注意库在部署时修改其运行时字节码以防范定期调用(guard against regular calls)。 与 .creationCode 有相同的限制,不能在合同本身或派生的合同访问此属性。 因为会引起循环引用。 除上面的属性, 下面的属性在接口类型I下可使用:

type(I).interfaceId

  • 返回接口I 的 bytes4 类型的接口 ID,接口 ID 参考: EIP-165 定义的, 接口 ID 被定义为 XOR (异或) 接口内所有的函数的函数选择器(除继承的函数。 对于整型 T 有T 的最小值(type(T).min)和T 的最大值(type(T).max)属性可访问。

内置函数产生随机数

依赖 block.timestamp 和 blockhash 产生随机数

  • 由于时间戳和区块哈希在一定程度上都可能受到挖矿矿工影响所以官方不推荐使用这种方式产生随机数,但在某些特殊用途的地方仍然是可用的。

  • 使用区块难度和时间戳生成的随机数也不是安全的。

Last updated