1. 程式人生 > >智慧合約語言 Solidity Solidity API

智慧合約語言 Solidity Solidity API

想知道更多區塊鏈知識,請百度【鏈客區塊鏈技術問答社群】

Solidity 是以太坊智慧合約程式語言,閱讀本文前,你應該對以太坊、智慧合約有所瞭解,如果你還不瞭解,建議你先看以太坊是什麼?

Solidity API 主要表現為Solidity 內建的特殊的變數及函式,他們存在於全域性名稱空間裡,主要分為以下幾類:
有關區塊和交易的屬性
ABI編碼函式
有關錯誤處理
有關數學及加密功能
地址相關
合約相關
下面詳細講解下
區塊和交易的屬性(Block And Transaction Properties)
用來提供一些區塊鏈當前的資訊。
blockhash(uint blockNumber) returns (bytes32):返回給定區塊號的雜湊值,只支援最近256個區塊,且不包含當前區塊。
block.coinbase (address): 當前塊礦工的地址。
block.difficulty (uint):當前塊的難度。
block.gaslimit (uint):當前塊的gaslimit。
block.number (uint):當前區塊的塊號。
block.timestamp (uint): 當前塊的Unix時間戳(從1970/1/1 00:00:00 UTC開始所經過的秒數)
gasleft() (uint256): 獲取剩餘gas。
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.sender,msg.value的值可以因為每一次外部函式呼叫,或庫函式呼叫發生變化(因為msg就是和呼叫相關的全域性變數)。
不應該依據 block.timestamp, now 和 block.blockhash來產生一個隨機數(除非你確實需要這樣做),這幾個值在一定程度上被礦工影響(比如在賭博合約裡,不誠實的礦工可能會重試去選擇一個對自己有利的hash)。
對於同一個鏈上連續的區塊來說,當前區塊的時間戳(timestamp)總是會大於上一個區塊的時間戳。
為了可擴充套件性的原因,你只能查最近256個塊,所有其它的將返回0.
ABI編碼函式
Solidity 提供了一下函式,用來直接得到ABI編碼資訊,這些函式有:

  • abi.encode(…) returns (bytes):計算引數的ABI編碼。
  • abi.encodePacked(…) returns (bytes):計算引數的緊密打包編碼
  • abi. encodeWithSelector(bytes4 selector, …) returns (bytes): 計算函式選擇器和引數的ABI編碼
  • abi.encodeWithSignature(string signature, …) returns (bytes): 等價於* abi.encodeWithSelector(bytes4(keccak256(signature), …)
    通過ABI編碼函式可以在不用呼叫函式的情況下,獲得ABI編碼值,下面通過一段程式碼來看看這些方式的使用:
    pragma solidity ^0.4.24;

contract testABI {
function abiEncode() public constant returns (bytes) {
abi.encode(1); // 計算 1 的ABI編碼
return abi.encodeWithSignature(“set(uint256)”, 1); //計算函式set(uint256) 及引數1 的ABI 編碼
}
}
錯誤處理
assert(bool condition)
用於判斷內部錯誤,條件不滿足時丟擲異常
require(bool condition):
用於判斷輸入或外部元件錯誤,條件不滿足時丟擲異常
require(bool condition, string message)
同上,多了一個錯誤資訊。
revert():
終止執行並還原改變的狀態
revert(string reason)
同上,提供一個錯誤資訊。
之前老的錯誤處理方式用throw 及 if … throw,這種方式會消耗掉所有剩餘的gas。目前throw 的方式已經被棄用。
數學及加密功能
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):
使用以太坊的(Keccak-256)計算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):
通過橢圓曲線簽名來恢復與公鑰關聯的地址,或者在錯誤時返回零。可用於簽名資料的校驗,如果返回結果是簽名者的公匙地址,那麼說明資料是正確的。
ecrecover函式需要四個引數,需要被簽名資料的雜湊結果值,r,s,v分別來自簽名結果串。
r = signature[0:64]
s = signature[64:128]
v = signature[128:130]
其中v取出來的值或者是00或01。要使用時,我們先要將其轉為整型,再加上27,所以我們將得到27或28。在呼叫函式時v將填入27或28。

用javascript表達如下:
var msg = ‘0x8CbaC5e4d803bE2A3A5cd3DbE7174504c6DD0c1C’

var hash = web3.sha3(msg)
var sig = web3.eth.sign(address, h).slice(2)
var r = 0x${sig.slice(0, 64)}
var s = 0x${sig.slice(64, 128)}
var v = web3.toDecimal(sig.slice(128, 130)) + 27
緊密打包引數(tightly packed)意思是說引數不會補位,是直接連線在一起的,下面幾個是相等的。
keccak256(“ab”, “c”)
keccak256(“abc”)

keccak256(0x616263) // hex
keccak256(6382179)
keccak256(97, 98, 99) //ascii
如果需要填充,可以使用顯式型別轉換: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的問題。一種解決辦法(workaround)是每個在你真正使用它們之前先發送1 wei到這些合約上來完成初始化。在官方和測試鏈上沒有這個問題。
地址相關
.balance (uint256):
Address的餘額,以wei為單位。

.transfer(uint256 amount):
傳送給定數量的ether到某個地址,以wei為單位。失敗時丟擲異常。
.send(uint256 amount) returns (bool):
傳送給定數量的ether到某個地址,以wei為單位, 失敗時返回false。
.call(…) returns (bool):
發起底層的call呼叫。失敗時返回false。
.callcode(…) returns (bool):
發起底層的callcode呼叫,失敗時返回false。
不鼓勵使用,未來可能會移除。
.delegatecall(…) returns (bool):
發起底層的delegatecall呼叫,失敗時返回false
更多資訊參考地址篇。
警告:send() 執行有一些風險:如果呼叫棧的深度超過1024或gas耗光,交易都會失敗。因此,為了保證安全,必須檢查send的返回值,如果交易失敗,會回退以太幣。如果用transfer會更好。
合約相關
this(當前合約的型別):
表示當前合約,可以顯式的轉換為Address
selfdestruct(address recipient):
銷燬當前合約,並把它所有資金髮送到給定的地址。
suicide(address recipient):
selfdestruct的別名
另外,當前合約裡的所有函式均可支援呼叫,包括當前函式本身。