1. 程式人生 > >Solidity語言學習筆記————7、單位和全域性變數

Solidity語言學習筆記————7、單位和全域性變數

貨幣單位(Ether Units)

weifinneyszaboether可以在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):完整的calldata
  • msg.gas (uint):剩餘的gas
  • msg.sender (address):訊息的傳送方(當前呼叫)
  • msg.sig (bytes4):calldata的前四個位元組(即函式識別符號)
  • msg.value (uint):所傳送的訊息中wei的數量
  • now (uint):當前塊時間戳(block.timestamp的別名)
  • tx.gasprice (uint):交易的gas價格
  • tx.origin (address):交易傳送方(完整的呼叫鏈)
註解
msg的所有成員的值,包括msg.sendermsg.value可以在每個external函式呼叫中改變。這包括呼叫庫函式。 如果你想在庫函式實現訪問限制使用msg.sender, 你必須手動設定msg.sender作為引數。
註解
不要依賴block.timestampnowblock.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裡,你可能在使用sha256ripemd160 或 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-level CALL, 失敗時返回false , 消耗所有可用gas, 可調整
  • <address>.callcode(...) returns (bool)
    發出 low-level CALLCODE, 失敗時返回false , 消耗所有可用gas, 可調整
  • <address>.delegatecall(...) returns (bool)
    發出 low-level DELEGATECALL, 失敗時返回false , 消耗所有可用gas, 可調整

欲瞭解更多資料,請參閱地址Address部分。

警告
使用send存在一些危險:如果呼叫堆疊深度為1024,則轉賬將失敗(呼叫程式始終強制執行此操作),並且如果接受者的gas耗盡,也會失敗。
因此,為了讓以太幣轉賬更安全,請務必檢查send的返回值,或者直接使用transfer那就更好了。
註解
callcode不建議使用,未來將會移除

合約相關(Contract Related)

  • this (current contract’s type)
    當前的合約,可顯式轉換為地址Address
  • selfdestruct(address): 
    銷燬當前合約,其資金髮送給指定的地址
  • suicide(address recipient): 
    selfdestruct的別名

此外,當前合同的所有函式均可以被直接呼叫,包括當前函式。