Solidity 语言内置特性

特殊变量及函数(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.timestamp
  • tx.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>.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(当前合约的类型) 当前合约的类型,可以显式的转换为Address
  • selfdestruct(address recipt) 销毁当前合约,并把它所有资金发送到给定的地址。

另外,当前合约里的所有函数均可支持调用,包括当前函数本身。

下一节:包括入参和出参、函数等