智能合約語言Solidity Solidity API

鏈客,專爲開發者而生,有問必答!javascript

此文章來自鏈客區塊鏈技術問答社區,未經容許拒絕轉載。java

圖片描述

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

Solidity API 主要表現爲Solidity 內置的特殊的變量及函數,他們存在於全局命名空間裏,主要分爲如下幾類:編程

有關區塊和交易的屬性安全

ABI編碼函數編程語言

有關錯誤處理ide

有關數學及加密功能函數

地址相關區塊鏈

合約相關測試

下面詳細講解下

區塊和交易的屬性(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) // hexkeccak256(6382179)keccak256(97, 98, 99) //ascii

若是須要填充,能夠使用顯式類型轉換:keccak256(「x00x12」) 與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的別名

另外,當前合約裏的全部函數都可支持調用,包括當前函數自己。

相關文章
相關標籤/搜索