iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 18
1
Blockchain

Smart Contract 開發 - 使用 Solidity系列 第 18

開發智能合約 - 單位和全域變數 (Day18)

貨幣單位 (Ether Units)

在數字的後面加上 weifinneyszaboether 轉換為貨幣的單位,如果沒有指定,基礎單位就是 wei

2 ehter == 2000 finney

時間單位 (Time Units)

在數字的後面加上 secondsminuteshoursdaysweeksyears 轉換為時間單位,如果沒有指定,基礎單位就是秒。

關於時間單位的比較:

  • 1 == 1 seconds
  • 1 minutes == 60 seconds
  • 1 hours == 60 minutes
  • 1 days == 24 hours
  • 1 weeks == 7 days
  • 1 years == 365 days

請小心的使用時間單位,因為有閏秒 (leap seconds),由於無法預測什麼時候發生閏秒,如果你需要使用精確的時間,需要透過外部函式庫來取得。

由於上述原因,years 被棄用了

範例

function f(uint start, uint daysAfter) public {
    uint afterAt = start + daysAfter * 1 days; (正確的用法)
    uint afterAt = start + daysAfter days; (錯誤的用法)
}

特殊變數和函式

一些特別的變數和函式,提供有關區塊鏈的資訊和常用工具函式,存取範圍是全域的。

區塊 (block)

  • block.gaslimit (uint): 目前區塊的 gas limit
  • block.number (uint): 目前區塊的編號
  • block.blockhash(uint blockNumber):區塊的 hash 值,只能用在最近的 256 各區塊,0.4.22 版之後被 blockhash(uint blockNumber) 取代。
  • block.coinbase (address): 目前的區塊礦工的位址
  • block.difficulty (uint): 目前的區塊難度
  • block.timestamp (uint): 目前區塊的時間戳

msg

  • msg.gas (uint): 剩餘的 gas,0.4.21 版後被廢棄,由 gasleft() 取代。
  • msg.sender (address): 發送訊息給函式的位址
  • msg.data (bytes): 完整的 calldata
  • msg.sig (bytes4): calldata 的前四個 bytes (例如 function identifier)
  • msg.value (uint): 發送多少以太幣(單位是 wei)

transaction

  • tx.gasprice (uint): 交易的 gas price
  • tx.origin (address): 交易的發送者

其他

  • this: 目前的合約
  • now: 目前時間,是 block.timestamp 的暱稱。
  • gasleft() returns (uint256): 剩餘 gas
  • keccak256([argument, ...]);
  • sha256([argument, ...]);
  • ripemd160([argument, ...]);

不要倚賴 block.timestampnowblockhash 當作隨機亂數的來源,除非你知道你在做什麼。區塊的時間戳和 hash 都某種程度受到礦工的影響,如果你拿這兩個值作為博弈應用,可能會被社群中居心不良的礦工破解。

錯誤處理 (Error Handling)

  • assert(bool condition):如果條件不滿足,transaction 會失敗,使用於內部錯誤。
  • require(bool condition):如果條件不符合,狀態會被還原,使用於輸入值得錯誤或外部元件。
  • require(bool condition, string message):同上,但可以自訂的錯誤訊息。
  • revert():執行會被終止,並回復到修改前的狀態。
  • revert(string reason):同上,但可以自訂錯誤訊息。

範例

require(owner != msg.sender);
require(owner != msg.sender, "no permission");
revert();
revert("OMG");

數學和加密函式

  • addmod(uint x, uint y, uint k) returns (uint):加法,支援的版本 0.5.0 開始。
  • mulmod(uint x, uint y, uint k) returns (uint):乘法,支援的版本 0.5.0 開始。
  • keccak256(...) returns (bytes32):計算傳入值的 Ethereum-SHA-3 (Keccak-256) hash,使用 tightly packed。
  • sha256(...) returns (bytes32):計算傳入值的 SHA-256 hash,使用 tightly packed。
  • sha3(...) returns (bytes32):keccak256 的別名
  • ripemd160(...) returns (bytes20):計算傳入值的 RIPEMD-160 hash,使用 tightly packed。
  • ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)

tightly packed 的意思是,計算時,會自動去掉空白 (padding)。

以下內容的值,完全相同。

keccak256("ab", "c")
keccak256("abc")
keccak256(0x616263)
keccak256(6382179)
keccak256(97, 98, 99)

位址相關

  • <address>.balance (uint256):餘額,值得單位是 wei
  • <address>.transfer(uint256 amount):轉錢給指定位址,值的單位是 wei,如果失敗會拋出錯誤訊息,需花費 2300 gas,gas 的設定不能調整。

合約相關

  • this:指當前的合約,可轉換為合約的地址。
  • selfdestruct(address recipient):銷毀目前合約,並把合約裡的錢轉到指定的位址。
  • suicide(address recipient):selfdestruct 的別名,已被廢棄不推薦使用。

範例

address(this);
selfdestruct(0xa77451687Ee77cB3DFf16A24446C54DB76C80222);

上一篇
開發智能合約 - 可見度和自動生成 getter 函示 (Day17)
下一篇
開發智能合約 - 實戰練習「簡易版 King of the Ether (1/2)」(Day19)
系列文
Smart Contract 開發 - 使用 Solidity31

尚未有邦友留言

立即登入留言