单位,和全局可用变量
Ether 单位
字面数字的后缀可以是 wei , gwei 或 ether 指定乙醚的子名称,其中不带后缀的乙醚编号假定为wei。
assert(1 wei == 1);
assert(1 gwei == 1e9);
assert(1 ether == 1e18);
子名称后缀的唯一作用是乘以10的幂。
注解
面额 finney 和 szabo 已在版本0.7.0中删除。
时间单位
后缀如下 seconds , minutes , hours , days 和 weeks after文字数字可用于指定时间单位,其中秒是基本单位,单位按以下方式简单地视为单位:
- 1 == 1 seconds
- 1 minutes == 60 seconds
- 1 hours == 60 minutes
- 1 days == 24 hours
- 1 weeks == 7 days
如果您使用这些单位执行日历计算,请注意,因为不是每年等于365天,甚至不是每天都有24小时,因为 leap seconds .由于无法预测闰秒,因此外部Oracle必须更新准确的日历库。
注解
后缀 years 已在0.5.0版中删除,原因如上。
这些后缀不能应用于变量。例如,如果要以天为单位解释函数参数,可以采用以下方式:
function f(uint start, uint daysAfter) public {
    if (block.timestamp >= start + daysAfter * 1 days) {
      // ...
    }
}
特殊变量和函数
有一些特殊的变量和函数,它们总是存在于全局名称空间中,主要用于提供关于区块链的信息,或者是通用的效用函数。
块和事务属性
- blockhash(uint blockNumber) returns (bytes32):给定挡路的散列时间- blocknumber是最近256个块中的一个;否则返回零
- block.basefee(- uint): current block's base fee (EIP-3198 and EIP-1559)
- block.chainid(- uint): current chain id
- block.coinbase(- address payable): current block miner's address
- block.difficulty(- uint): current block difficulty
- block.gaslimit(- uint): current block gaslimit
- block.number(- uint): current block number
- block.timestamp(- uint): current block timestamp as seconds since unix epoch
- gasleft() returns (uint256):剩余气体
- msg.data(- bytes calldata): complete calldata
- msg.sender(- address): sender of the message (current call)
- msg.sig(- bytes4): first four bytes of the calldata (i.e. function identifier)
- msg.value(- uint): number of wei sent with the message
- tx.gasprice(- uint): gas price of the transaction
- tx.origin(- address): sender of the transaction (full call chain)
注解
所有成员的值 msg 包括 msg.sender 和 msg.value 每个人都可以改变 外部的 函数调用。这包括对库函数的调用。
注解
当对合同进行离链评估时,而不是在挡路中包含的交易上下文中进行评估时,您不应假设 block.* 和 tx.* 指的是任何特定挡路或交易的价值。这些值由执行契约的EVM实现提供,可以是任意的。
注解
不要依赖 block.timestamp 或 blockhash 作为随机性的来源,除非你知道你在做什么。
时间戳和块散列在某种程度上都会受到矿工的影响。例如,采矿社区中的坏参与者可以在所选哈希上运行赌场付款函数,如果他们没有收到任何钱,只需重试其他哈希。
当前块时间戳必须严格大于最后一个块的时间戳,但唯一的保证是它将介于规范链中两个连续块的时间戳之间。
注解
由于可伸缩性的原因,块散列不能用于所有块。您只能访问最近256个块的哈希值,所有其他值都将为零。
注解
函数 blockhash 以前被称为 block.blockhash ,在0.4.22版中已弃用,在0.5.0版中已删除。
注解
函数 gasleft 以前被称为 msg.gas ,在0.4.21版中已弃用,在0.5.0版中已删除。
注解
在版本0.7.0中,别名 now (用于 block.timestamp )已删除。
ABI编解码功能
- abi.decode(bytes memory encodedData, (...)) returns (...): ABI-decodes the given data, while the types are given in parentheses as second argument. Example:- (uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))
- abi.encode(...) returns (bytes memory):abi对给定参数进行编码
- abi.encodePacked(...) returns (bytes memory):执行 packed encoding 给出的参数。请注意,压缩编码可能不明确!
- abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory):abi从第二个开始对给定参数进行编码,并在给定的四字节选择器前面加上前缀。
- abi.encodeWithSignature(string memory signature, ...) returns (bytes memory): Equivalent to- abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`
注解
这些编码函数可以用来处理外部函数调用的数据,而无需实际调用外部函数。此外, keccak256(abi.encodePacked(a, b)) 是计算结构化数据散列的一种方法(尽管要注意,可以使用不同的函数参数类型来构造“散列冲突”)。
请参阅有关 ABI 以及 tightly packed encoding 有关编码的详细信息。
字节的成员
- bytes.concat(...) returns (bytes memory): Concatenates variable number of bytes and bytes1, ..., bytes32 arguments to one byte array
错误处理
请参见 assert and require 有关错误处理和何时使用哪个函数的详细信息。
- assert(bool condition)
- 导致死机错误,从而在不满足条件时返回状态更改-用于内部错误。 
- 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.断言- k != 0从0.5.0版开始。
- mulmod(uint x, uint y, uint k) returns (uint)
- 计算 - (x * y) % k其中乘法是以任意精度执行的,而不是在- 2**256.断言- k != 0从0.5.0版开始。
- keccak256(bytes memory) returns (bytes32)
- 计算输入的keccak-256哈希 
注解
以前有个别名 keccak256 打电话 sha3 ,已在0.5.0版中删除。
- 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)
- 从椭圆曲线签名中恢复与公钥关联的地址,或者在出错时返回零。函数参数对应签名的ECDSA值: - r=签名的前32个字节
- s=第二个32字节的签名
- v=签名的最后1个字节
 - ecrecover返回一个- address,而不是- address payable. 见 address payable 转换时,如果您需要将资金转移到恢复的地址。- 有关更多详细信息,请阅读 example usage . 
警告
如果你使用 ecrecover 请注意,有效签名可以转换为不同的有效签名,而不需要知道相应的私钥。在宅基地的硬叉子里,这个问题被解决了 _transaction_ 签名(参见 EIP-2 ,但ecrecover功能保持不变。
这通常不是问题,除非您要求签名是唯一的或使用它们来标识项目。OpenZeppelin有一个 ECDSA helper library 可以用作包装 ecrecover 没有这个问题。
注解
运行 sha256 , ripemd160 或 ecrecover 在一 私有区块链 你可能会遇到没油的情况。这是因为这些函数是作为“预编译契约”实现的,并且只在它们收到第一条消息后才真正存在(尽管它们的契约代码是硬编码的)。发送给非现有合同的消息成本更高,因此执行过程中可能会遇到耗尽天然气的错误。解决这个问题的方法是,在实际合同中使用每个合同之前,首先将wei(例如1)发送给每个合同。这不是主网络或测试网络上的问题。
地址类型的成员
- <address>.balance(- uint256)
- 平衡 地址 在魏 
- <address>.code(- bytes memory)
- 代码位于 地址 (可以为空) 
- <address>.codehash(- bytes32)
- 的代码散列。 地址 
- <address payable>.transfer(uint256 amount)
- 将给定数量的wei发送到 地址 ,故障时恢复,向前2300气体津贴,不可调 
- <address payable>.send(uint256 amount) returns (bool)
- 将给定数量的wei发送到 地址 回报 - false故障时,向前2300气体津贴,不可调
- <address>.call(bytes memory) returns (bool, bytes memory)
- 发布低级 - CALL对于给定的有效载荷,返回成功条件和返回数据,转发所有可用气体,可调
- <address>.delegatecall(bytes memory) returns (bool, bytes memory)
- 发布低级 - DELEGATECALL对于给定的有效载荷,返回成功条件和返回数据,转发所有可用气体,可调
- <address>.staticcall(bytes memory) returns (bool, bytes memory)
- 发布低级 - STATICCALL对于给定的有效载荷,返回成功条件和返回数据,转发所有可用气体,可调
有关详细信息,请参见 地址 .
警告
你应该避免使用 .call() 尽可能在执行另一个协定函数时,因为它会绕过类型检查、函数存在性检查和参数打包。
警告
使用中有一些危险 send :如果调用堆栈深度为1024,则传输失败(调用方始终可以强制执行此操作),如果收件人耗尽气体,则传输也会失败。因此,为了安全传输 Ether  ,请始终检查 send 使用 transfer 或者更好:使用收款人取款的模式。
警告
由于EVM认为对不存在的约定的调用总是成功的,因此稳定性包括使用 extcodesize 执行外部呼叫时的操作码。这可以确保将要调用的协定要么实际存在(它包含代码),要么引发异常。
对地址而不是合同实例进行操作的低级调用(即 .call() , .delegatecall() , .staticcall() , .send() 和 .transfer() ) 请勿 包括这张支票,这会使他们的汽油更便宜,但也不太安全。
注解
在0.5.0版本之前,solidity允许合同实例访问地址成员,例如 this.balance .现在禁止这样做,必须进行到地址的显式转换: address(this).balance .
注解
如果状态变量是通过低级的delegatecall访问的,则两个契约的存储布局必须对齐,以便被调用的契约能够按名称正确访问调用契约的存储变量。当然,如果将存储指针作为函数参数传递,就像在高级库中那样,情况就不是这样了。
注解
在0.5.0版之前, .call , .delegatecall 和 .staticcall 只返回成功条件,不返回返回数据。
注解
在0.5.0版本之前,有一个成员 callcode 语义学与 delegatecall .
类型信息
表达式 type(X) 可用于检索有关类型的信息 X . 目前,对该功能的支持有限 (X 可以是协定或整数类型),但将来可能会对其进行扩展。
以下属性可用于合同类型 C :
- type(C).name
- 合同的名称。 
- type(C).creationCode
- 包含协定的创建字节码的内存字节数组。这可以在内联程序集中用于构建自定义创建例程,特别是通过使用 - create2操作码。此属性可以 not 在合同本身或任何派生合同中访问。它使字节码包含在调用站点的字节码中,因此不可能像这样循环引用。
- type(C).runtimeCode
- 包含协定的运行时字节码的内存字节数组。这是通常由 - C.如果- C具有使用内联程序集的构造函数,这可能与实际部署的字节码不同。还请注意,库在部署时修改其运行时字节码,以防止常规调用。与- .creationCode同时申请此属性。
除上述属性外,以下属性也可用于接口类型 I :
- type(I).interfaceId:
- A - bytes4包含 EIP-165 给定接口的接口标识符- I. 此标识符定义为- XOR在接口本身定义的所有函数选择器中-不包括所有继承的函数。
以下属性可用于整数类型 T :
- type(T).min
- 按最小类型表示的值 - T.
- type(T).max
- 按类型表示的最大值 - T.