单位,和全局可用变量
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 idblock.coinbase
(address payable
): current block miner's addressblock.difficulty
(uint
): current block difficultyblock.gaslimit
(uint
): current block gaslimitblock.number
(uint
): current block numberblock.timestamp
(uint
): current block timestamp as seconds since unix epochgasleft() returns (uint256)
:剩余气体msg.data
(bytes calldata
): complete calldatamsg.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 messagetx.gasprice
(uint
): gas price of the transactiontx.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 toabi.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
.