Solidity語言學習筆記————7、單位和全域性變數
阿新 • • 發佈:2019-02-20
貨幣單位(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
的別名
此外,當前合同的所有函式均可以被直接呼叫,包括當前函式。