货币单位(Ether Units)
wei
,finney
,szabo
或ether
可以在Solidity中作为货币单位并可以进行相互转换。没有单位的数字默认是Wei。单位之间的转化规则如下:
- 1 ether == 10^3 finney
- 1 ether == 10^6 szabo
- 1 ether == 10^18 wei
例如,表达式2 ether == 2000 finney
返回值为true
时间单位(Time Units)
seconds
秒, minutes
分, hours
时, days
天, weeks
周, years
年可以在Solidity中作为时间单位,单位之间转化规则如下:
- 1 == 1 seconds
- 1 minutes == 60 seconds
- 1 hours == 60 minutes
- 1 days == 24 hours
- 1 weeks == 7 days
- 1 years == 365 days
请小心使用这些单位进行日历计算,因为不是每年都等于365天,甚至因为闰秒leap seconds,不是每天都有24小时。 由于闰秒无法预测,因此必须通过外部预言(external oracle)更新精确的日历库。
这些后缀只能用于字面量,不能应用于变量。 如果你说明变量的单位,例如days
,你可以通过以下方式做到这一
function f(uint start, uint daysAfter) public { if (now >= start + daysAfter * 1 days) { // ... } }
特殊变量和函数(Special Variables and Functions)
全局命名空间中总是存在特殊变量和函数,主要用于提供有关区块链的信息。
区块和交易属性(Block and Transaction Properties)
block.blockhash(uint blockNumber) returns (bytes32)
: 给定区块的哈希值 - 仅适用于最新的256个区块,不包括当前区块block.coinbase
(address
):当前区块的矿工的地址block.difficulty
(uint
):当前区块的难度系数block.gaslimit
(uint
):当前区块gas限制block.number
(uint
):当前区块编号block.timestamp
(uint
):当前块的时间戳msg.data
(bytes
):完整的calldatamsg.gas
(uint
):剩余的gasmsg.sender
(address
):消息的发送方(当前调用)msg.sig
(bytes4
):calldata的前四个字节(即函数标识符)msg.value
(uint
):所发送的消息中wei的数量now
(uint
):当前块时间戳(block.timestamp
的别名)tx.gasprice
(uint
):交易的gas价格tx.origin
(address
):交易发送方(完整的调用链)
注解 |
---|
msg 的所有成员的值,包括msg.sender 和msg.value 可以在每个external函数调用中改变。这包括调用库函数。 如果你想在库函数实现访问限制使用msg.sender , 你必须手动设置msg.sender 作为参数。 |
注解 |
---|
不要依赖block.timestamp ,now 和block.blockhash 作为随机源 |
时间戳timestamp 和区块哈希blockhash 在一定程度上会受到矿工的影响。 |
例如,矿区中的坏节点可以对选定的哈希运行casino payout函数,如果他们没有收到任何钱,只需重试不同的哈希。 |
当前块时间戳必须严格大于最后一个块的时间戳,但唯一的保证是它将位于规范链中两个连续块的时间戳之间的某处。 由于区块链是增长可变的,所以不能获取整个区块链的哈希值。 您只能访问最近256个区块的哈希值,其他所有值都将为0。 |
错误处理(Error Handling)
assert(bool condition)
:如果条件不满足则抛出异常 - 用于内部错误。require(bool condition)
:如果条件不满足则抛出异常 - 用于输入或外部组件中的错误。revert()
:中止执行并恢复状态更改
数学和加密功能(Mathematical and Cryptographic Functions)
addmod(uint x, uint y, uint k) returns (uint)
:
计算(x + y)%k
的值,其中加法以指定精度执行,并且不超过2 ** 256
。从版本0.5.0开始断言k!= 0
。mulmod(uint x, uint y, uint k) returns (uint)
:
计算(x * y)%k
的值,其中乘法以指定精度执行,并且不超过2 ** 256
。从版本0.5.0开始断言k!= 0
keccak256(...) returns (bytes32)
:
计算(紧凑排列的)参数的Ethereum-SHA-3的Hash值值sha256(...) returns (bytes32)
:
计算(紧凑排列的)参数的SHA-256 的Hash值sha3(...) returns (bytes32)
:keccak256
的别名ripemd160(...) returns (bytes20)
:
计算(紧凑排列的)参数的 RIPEMD-160 的Hash值ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
:
从椭圆曲线签名中恢复与公钥相关的地址,或在错误时返回零
在上述中,“紧凑排列”,意思是没有填充的参数的连续排列,也就是下面表达式是没有区别的:
keccak256("ab", "c") keccak256("abc") keccak256(0x616263) keccak256(6382179) keccak256(97, 98, 99)
如果需要填充,可以使用显式类型转换:
keccak256(0) == keccak256(uint8(0))
,
keccak256(0x12345678) == keccak256(uint32(0x12345678))
在一个私有的blockchain里,你可能在使用sha256
, ripemd160
或 ecrecover
的时候碰到”Out-of-Gas”的问题 。原因在于这个仅仅是预编译的合约,合约要在他们接到的第一个消息以后才真正的生成(虽然他们的合约代码是硬编码的)。对于没有真正生成的合约的消息是非常昂贵的,这时就会碰到“Out-of-Gas”的问题。 这一问题的解决方法是事先把1wei 发送到各个你当前使用的各个合约上。这不是官方或测试网的问题。
地址相关(Address Related)
<address>.balance
(uint256
):
该地址的余额,单位是Wei<address>.transfer(uint256 amount)
:
给该地址发送金额,单位是Wei,发送失败抛出异常,消耗2300 gas 费用,不可调整<address>.send(uint256 amount) returns (bool)
:
给该地址发送金额,单位是Wei,发送失败返回false
,消耗2300 gas 费用,不可调整<address>.call(...) returns (bool)
:
发出 low-levelCALL
, 失败时返回false
, 消耗所有可用gas, 可调整<address>.callcode(...) returns (bool)
:
发出 low-levelCALLCODE
, 失败时返回false
, 消耗所有可用gas, 可调整<address>.delegatecall(...) returns (bool)
:
发出 low-levelDELEGATECALL
, 失败时返回false
, 消耗所有可用gas, 可调整
欲了解更多资料,请参阅地址Address部分。
警告 |
---|
使用send 存在一些危险:如果调用堆栈深度为1024,则转账将失败(调用程序始终强制执行此操作),并且如果接受者的gas耗尽,也会失败。 |
因此,为了让以太币转账更安全,请务必检查send 的返回值,或者直接使用transfer 那就更好了。 |
注解 |
---|
callcode 不建议使用,未来将会移除 |
合约相关(Contract Related)
this
(current contract’s type):
当前的合约,可显式转换为地址Addressselfdestruct(address)
:
销毁当前合约,其资金发送给指定的地址suicide(address recipient)
:selfdestruct
的别名
此外,当前合同的所有函数均可以被直接调用,包括当前函数。