特殊变量及函数(Special Variables and Functions)
有一些变量和函数存在于¥全局上下文中。主要用来提供一些区块链当前的信息。
- 区块和交易的属性(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)
当前块的时间戳。msg.data (bytes)
完整的调用数据(calldata)。msg.gas (uint)
当前还剩的gas。msg.sender (address)
当前调用发起人的地址。msg.sig (bytes4)
调用数据的前四个字节(函数标识符)。msg.value (uint)
这个消息所附带的货币量,单位为wei。now (uint)
当前块的时间戳,等同于block.timestamptx.gasprice (uint)
交易的gas价格。tx.origin (address)
交易的发送者(完整的调用链)
msg的所有成员值,如msg.sender,msg.value的值可以因为每一次外部函数调用,或库函数调用发生变化(因为msg就是和调用相关的全局变量)。
如果你想在库函数中,用msg.sender实现访问控制,你需要将msg.sender做为参数(就是说不能使用默认的msg.value,因为它可能被更改)。
为了可扩展性的原因,你只能查最近256个块,所有其它的将返回0.
数学和加密函数(Mathematical and Cryptographic Functions)
asser(bool condition)
如果条件不满足,抛出异常。addmod(uint x, uint y, uint k) returns (uint)
计算(x + y) % k。加法支持任意的精度。但不超过(wrap around?)2**256。mulmod(uint x, uint y, uint k) returns (uint)
计算(x * y) % k。乘法支持任意精度,但不超过(wrap around?)2**256。keccak256(...) returns (bytes32):
使用以太坊的(Keccak-256)计算HASH值。紧密打包。sha3(...) returns (bytes32)
等同于keccak256()。紧密打包。sha256(...) returns (bytes32)
使用SHA-256计算HASH值。紧密打包。ripemd160(...) returns (bytes20)
使用RIPEMD-160计算HASH值。紧密打包。ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
通过签名信息恢复非对称加密算法公匙地址。如果出错会返回0.revert()
取消执行,并回撤状态变化。需要注意的是参数是“紧密打包(tightly packed)”的,意思是说参数不会补位,就直接连接在一起的。
下面来看一个例子:
keccak256("ab", "c")
keccak256("abc")
//hex
keccak256(0x616263)
keccak256(6382179)
//ascii
keccak256(97, 98, 99)
上述例子中,三种表达方式都是一致的。如果需要补位,需要明确的类型转换,如:
keccak256("\x00\x12")等同于keccak256(uint16(0x12))
需要注意的是字面量会用,尽可能小的空间来存储它们。比如,keccak256(0) == keccak256(uint8(0)),keccak256(0x12345678) == keccak256(uint32(0x12345678))
在私链(private blockchain)上运行sha256,ripemd160或ecrecover可能会出现Out-Of-Gas报错。因为它们实现了一种预编译的机制,但合约要在收到第一个消息后才会存在。向一个不存在的合约发送消息,非常昂贵,所以才会导致Out-Of-Gas的问题。一种解决办法是每个在你真正使用它们前,先发送1 wei到这些合约上来完成初始化。在官方和测试链上没有这个问题。
地址相关(Address Related)
<address>.balance(unit256)
Address的余额,以wei为单位。<address>.transfer(uint256 amount)
发送给定数量的ether,以wei为单位,到某个地址。失败时抛出异常。<address>.send(uint256 amount) returns (bool)
发送给定数量的ether,以wei为单位,到某个地址。失败时返回false。<address>.call(...) returns (bool)
发起底层的call调用。失败时返回false。<address>.callcode(...) returns (bool)
发起底层的callcode调用,失败时返回false。<address>.delegatecall(...) returns (bool)
发起底层的delegatecall调用,失败时返回false。
使用send方法需要注意,调用栈深不能超过1024,或gas不足,都将导致发送失败。使用为了保证你的ether安全,要始终检查返回结果。当用户取款时,使用transfer或使用最佳实践的模式2。
合约相关
this(当前合约的类型)
当前合约的类型,可以显式的转换为Addressselfdestruct(address recipt)
销毁当前合约,并把它所有资金发送到给定的地址。
另外,当前合约里的所有函数均可支持调用,包括当前函数本身。
下一节:包括入参和出参、函数等