1. 程式人生 > >以太坊:Solidity語言

以太坊:Solidity語言

轉載請註明出處:https://www.cnblogs.com/zhizaixingzou/p/10122356.html

 

目錄

 

1. Solidity語言

下面的截圖說明來自:https://solidity-cn.readthedocs.io/zh/develop/

1.1. 為建立智慧合約而設計的語言

Solidity是一門程式設計語言,為建立能在EVM上執行的智慧合約而設計

 

目前,編寫Solidity程式碼最好的IDERemix,它是基於瀏覽器的線上IDE,0.4.24版本編譯器對應的網址為:

https://remix.ethereum.org/#optimize=true&version=soljson-v0.4.24+commit.e67f0147.js

 

Solidity原始碼例項如下。

編譯後得到的就是能在EVM中執行的位元組序列。

608060405234801561001057600080fd5b5060bf8061001f6000396000f30060806040526004361060485763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166360fe47b18114604d5780636d4ce63c146064575b600080fd5b348015605857600080fd5b5060626004356088565b005b348015606f57600080fd5b506076608d565b60408051918252519081900360200190f35b600055565b600054905600a165627a7a72305820d8a40958ffb63a1d224c2c1e92ac7306393c0e262ecadd190cbcf6139159ffef0029

其彙編如下。

PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xBF DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x48 JUMPI PUSH4 0xFFFFFFFF PUSH29 0x100000000000000000000000000000000000000000000000000000000 PUSH1 0x0 CALLDATALOAD DIV AND PUSH4 0x60FE47B1 DUP2 EQ PUSH1 0x4D JUMPI DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x64 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x58 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x62 PUSH1 0x4 CALLDATALOAD PUSH1 0x88 JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x6F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x76 PUSH1 0x8D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x0 SSTORE JUMP JUMPDEST PUSH1 0x0 SLOAD SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0xd8 LOG4 MULMOD PC SELFDESTRUCT 0xb6 GASPRICE SAR 0x22 0x4c 0x2c 0x1e SWAP3 0xac PUSH20 0x6393C0E262ECADD190CBCF6139159FFEF002900

1.2. 基本語法

1.2.1. 所有識別符號只能使用ASCII字符集

所有的識別符號都只能使用ASCII字符集。但字串變數可以儲存UTF-8編碼的資料。

1.2.2. 指定Solidity版本

pragma solidity ^0.4.12;

告訴大家原始碼使用Solidity版本0.4.12寫的。某個編譯器版本如果支援Solidity的某個版本,那麼它也會支援Solidity該版本的之前的任何版本。

1.2.3. 定義合約

contract DataStore {……}

定義一個合約。可以將合約類比Java的類,它也包含了狀態和行為。由於以太坊區塊鏈的類似版本控制系統的設計,隨著區塊的增加,狀態會被覆蓋,但都是以增量的形式,也就是說,歷史狀態不會被刪除。

1.2.4. 宣告一個public的變數

uint256 public data;

public會使自動生成一個函式,允許你在這個合約之外訪問這個狀態變數的當前值。生成的函式為:data()

1.2.5. 宣告和觸發事件

event Sent(address from, address to, uint amount);

聲明瞭一個事件

 

emit Sent(msg.sender, receiver, amount);

觸發一個指定的事件。

 

事件在區塊鏈中被記錄為日誌,被索引的引數會生成布隆過濾器,記錄到引數級、事件級、交易級、區塊級等不同層級的布隆過濾器,以便高效地查詢日誌。

 

anonymous 修飾事件時不把事件簽名作為 topic 儲存。

 

indexed 修飾事件引數將引數作為 topic 儲存。

event Deposit(

    address indexed _from,

    bytes32 indexed _id,

    uint _value

);

 

logi 接受 i + 1 個 bytes32 型別的引數。其中第一個引數會被用來做為日誌的資料部分, 其它的會做為 topic

其中的長十六進位制數的計算方法是 keccak256("Deposit(address,hash256,uint256)"),即事件的簽名。

1.2.6. mapping型別

mapping (address => uint) public balances;

balances[receiver] += amount;

或者balances(receiver)

 

在對映中,實際上並不儲存 key,而是儲存它的 keccak256 雜湊值,從而便於查詢實際的值。

1.2.7. 獲取源外部交易的發起者

msg.sender

1.2.8. 定義構造方法

如何用為Coin的構造方法:

function Coin() public {

    minter = msg.sender;

}

 

也可以如下:

constructor(uint256 x) public {

    data = x;

}

1.2.9. if語句

if (msg.sender != minter) return;

 

if (delegate_.voted) {

    proposals[delegate_.vote].voteCount += sender.weight;

} else {

    delegate_.weight += sender.weight;

}

1.2.10. 進入下一迴圈項

continue;

1.2.11. 定義函式

function send(address receiver, uint amount) public {

 

合約中的函式本身預設是 public

1.2.12. 函式型別

function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]

此為宣告函式型別的模板,注意這裡是型別,而非函式本身。

 

函式型別預設是內部函式,因此不需要宣告 internal 關鍵字。

 

function map(uint[] memory self, function (uint) pure returns (uint) f) internal pure returns (uint[] memory r)

{

  r = new uint[](self.length);

  for (uint i = 0; i < self.length; i++) {

    r[i] = f(self[i]);

  }

}

1.2.13. ABI函式選擇器

function f() public view returns (bytes4) {

  return this.f.selector;

}

可以返回 ABI 函式選擇器

1.2.14. 合約自毀

function kill() public {

   if (owner == msg.sender) {

      selfdestruct(owner);

   }

}

selfdestruct執行後,合約賬戶上剩餘的以太幣會發送給指定的目標,然後其儲存和程式碼從狀態中被移除,這是合約程式碼從區塊鏈上移除的唯一方式

1.2.15. 複合型別

struct Proposal {

    bytes32 name;

    uint voteCount;

}

定義一個複合型別。

 

Proposal({

                name: proposalNames[i],

                voteCount: 0

            })

建立一個複合型型別的物件。

 

proposal.name = “Mr.Bit”;

訪問複合型別的成員。

1.2.16. 陣列

Proposal[] public proposals;

proposals.push(proposal)

 

delete proposals

Proposals.Length=0

清空陣列。

 

變長的 儲存(storage) 陣列以及 bytes 型別(而不是 string 型別)都有一個叫做 push 的成員函式,它用來附加新的元素到陣列末尾。 這個函式將返回新的陣列長度。

1.2.17. for語句

for (uint i = 0; i < proposalNames.length; i++) {……}

1.2.18. 引數校驗

require(

    msg.sender == chairperson,

    "Only chairperson can give right to vote."

);

如果交易不過,那麼合約執行就會返回REVERT。此語句不需要一定出現在函式的開頭。

 

可以定義修飾符來實現入參校驗:

modifier onlyBefore(uint _time) { require(now < _time); _; }

function reveal(

    uint[] _values,

    bool[] _fake,

    bytes32[] _secret

) public onlyAfter(biddingEnd) onlyBefore(revealEnd) {

新的函式體是由 modifier 本身的函式體,並用原函式體替換 `_;` 語句來組成的。

1.2.19. while語句

while (voters[to].delegate != address(0)) {……}

1.2.20. 函式返回值

function winnerName() public view

        returns (bytes32 winnerName_, unit count_)

{

winnerName_ = proposals[winningProposal()].name;

count_ = 9;

}

這裡直接指明返回變數,然後函式內賦值。

 

但如果只返回一個值,則可以如下不指明返回值名稱。

function get() public view returns (uint256) {

    return data;

}

 

如果無返回值,則可呼叫“return;”或者最後一個語句執行完後就自然返回。

1.2.21. payable修飾函式可以接收轉賬

function bid() public payable {

表示此方法的呼叫可接受value值不為0

1.2.22. 轉給某地址一定金額

beneficiary.transfer(highestBid);

向beneficiary增加highestBid數量的金額。

金額單位預設是wei,如果不是,則可以顯式指定:wei、 finney、 szabo 或 ether

1.2.23. 同時給多個變數賦值

(uint value, bool fake, bytes32 secret) =

                    (_values[i], _fake[i], _secret[i]);

1.2.24. internal修飾符

function placeBid(address bidder, uint value) internal

            returns (bool success) {

internal函式只能在本合約(或繼承合約)內被呼叫

1.2.25. 列舉型別

enum State { Created, Locked, Inactive }

 

State public state;

state = State.Inactive;

uint(state);

1.2.26. 獲取本合約的餘額

address(this).balance

1.2.27. 註釋

可以使用單行註釋(//)和多行註釋(/*...*/

有另一種註釋稱為 natspec 註釋,它們是用三個反斜槓(///)或雙星號開頭的塊(/** ... */)書寫

1.2.28. 值型別

這些型別的變數將始終按值來傳遞。 也就是說,當這些變數被用作函式引數或者用在賦值語句中時,總會進行值拷貝。

 

bool :可能的取值為字面常數值 true 和 false 

運算子:

  • ! (邏輯非)
  • && (邏輯與, "and" ,遵循短路規則
  • || (邏輯或, "or" ,遵循短路規則
  • == (等於)
  • != (不等於)

 

int / uint :分別表示有符號和無符號的不同位數的整型變數。 支援關鍵字 uint8 到 uint256以及 int8 到 int256,以 8 位為步長遞增。 uint 和 int 分別是 uint256 和 int256 的別名。

運算子:

  • 比較運算子: <= , < , == , != , >= , > (返回布林值)
  • 位運算子: & , | , ^ (異或), ~ (位取反)
  • 算數運算子: + , - , 一元運算 - , 一元運算 + , * , / , % (取餘) , ** (冪), << (左移位) , >> (右移位)

 

Solidity 還沒有完全支援定長浮點型。

 

address:地址型別儲存一個 20 位元組的值(以太坊地址的大小)。

地址字面常數:比如像 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF 這樣的通過了地址校驗和測試的十六進位制字面常數屬於 address 型別。

myAddress.balance

myAddress.transfer(10);,失敗則拋異常。

myAddress.send(10),transfer的低版本保留,目前不建議用,失敗返回false。

myAddress.call(bytes4(keccak256("fun(uint256)")), a);返回的布林值表明了被呼叫的函式已經執行完畢(true)或者引發了一個 EVM 異常(false)。 無法訪問返回的真實資料(為此我們需要事先知道編碼和大小)。

 

定長位元組陣列:bytes1, bytes2, bytes3, ..., bytes32。byte 是 bytes1 的別名。

運算子:

  • 比較運算子:<=, <, ==, !=, >=, > (返回布林型)
  • 位運算子: &, |, ^ (按位異或), ~ (按位取反), << (左移位), >> (右移位)
  • 索引訪問:如果 x 是 bytesI 型別,那麼 x[k] (其中 0 <= k < I)返回第 k 個位元組(只讀)。

bytes.length 表示這個位元組陣列的長度(只讀)

1.2.29. 匯入原始檔

import "filename";

從 “filename” 中匯入所有的全域性符號到當前全域性作用域中

以 / 作為目錄分割符以 . 標示當前目錄以 .. 表示父目錄。

import "./SafeMath.sol";

 

import * as symbolName from "filename";

某些情況下可以用:import "filename" as symbolName;

 

 

import {symbol1 as alias, symbol2} from "filename";

1.2.30. 

內部函式可以在內部庫函式中使用,因為它們會成為同一程式碼上下文的一部分

 

指令 using A for B; 可用於附加庫函式(從庫 A)到任何型別(B)。 這些函式將接收到呼叫它們的物件作為它們的第一個引數

using A for *; 的效果是,庫 A 中的函式被附加在任意的型別上。

1.2.31. 合約呼叫合約

1.2.32. 引用型別

變長位元組陣列:

bytes:變長位元組陣列

string:變長 UTF-8 編碼字串型別

字串字面常數是指由雙引號或單引號引起來的字串("foo" 或者 'bar'可以隱式地轉換成 bytes1,……,bytes32,如果合適的話,還可以轉換成 bytes 以及 string

字串字面常數支援轉義字元,例如 \n,\xNN 和 \uNNNN。\xNN 表示一個 16 進位制值,最終轉換成合適的位元組, 而 \uNNNN 表示 Unicode 編碼值,最終會轉換為 UTF-8 的序列。

十六進位制字面常數以關鍵字 hex 打頭,後面緊跟著用單引號或雙引號引起來的字串(例如,hex"001122FF")。 字串的內容必須是一個十六進位制的字串,它們的值將使用二進位制表示。十六進位制字面常數跟字串字面常數很類似,具有相同的轉換規則。

bytes 類似於 byte[],但它在 calldata 中會被緊打包將元素連續地存在一起,不會按每 32 位元組一單元的方式來存放。

 

所有的複雜型別,即 陣列 結構 型別,都有一個額外屬性,“資料位置,說明資料是儲存在記憶體還是儲存中。根據上下文不同,大多數時候資料有預設的位置,但也可以通過在型別名後增加關鍵字 storage 或 memory 進行修改。 函式引數(包括返回的引數)的資料位置預設是 memory區域性變數的資料位置預設是 storage,狀態變數的資料位置強制是 storage (這是顯而易見的)。也存在第三種資料位置, calldata ,這是一塊只讀的。 外部函式的引數(非返回引數)的資料位置被強制指定為 calldata

在 儲存(storage) 和 記憶體(memory) 之間兩兩賦值,或者 儲存(storage) 向狀態變數(甚至是從其它狀態變數)賦值都會建立一份獨立的拷貝。 然而狀態變數向區域性變數賦值時僅僅傳遞一個引用,而且這個引用總是指向狀態變數,因此後者改變的同時前者也會發生改變。 另一方面,從一個 記憶體(memory) 儲存的引用型別向另一個 記憶體(memory) 儲存的引用型別賦值並不會建立拷貝。

 

可使用 new 關鍵字在記憶體中建立變長陣列。

1.2.33. 指定儲存位置

uint[] memory a = new uint[](7);

Voter storage sender = voters[msg.sender];

1.2.34. 定長陣列字面常量

[uint(1), 3, 4]為unint[3] memory型別,而非unint[]型別。

1.2.35. 合約建立合約

MappingExample m = new MappingExample();

1.2.36. 重置操作delete

delete a 的結果是將 a 的型別在初始化時的值賦值給 a。即對於整型變數來說,相當於 a = 0但 delete 也適用於陣列,對於動態陣列來說,是將陣列的長度設為 0,而對於靜態陣列來說,是將陣列中的所有元素重置。 如果物件是結構體,則將結構體中的所有屬性重置。

1.2.37. 隱式轉換

一般來說,只要值型別之間的轉換在語義上行得通,而且轉換的過程中沒有資訊丟失,那麼隱式轉換基本都是可以實現的: uint8 可以轉換成 uint16,int128 轉換成 int256,但 int8 不能轉換成 uint256 (因為 uint256 不能涵蓋某些值,例如,-1)。 更進一步來說,無符號整型可以轉換成跟它大小相等或更大的位元組型別,但反之不能。 任何可以轉換成 uint160 的型別都可以轉換成 address 型別。

1.2.38. 顯式轉換

int8 y = -3;

uint x = uint(y);

1.2.39. 本地變數

uint24 x = 0x123;

var y = x;

1.2.40. 時間單位

 

auctionEnd = now + _biddingTime;

now返回當前區塊的時間戳。

 

秒是預設時間單位,在時間單位之間,數字後面帶有 seconds、 minutes、 hours、 days、 weeks 和 years 的可以進行換算

if (now >= start + daysAfter * 1 days) {

1.2.41. 全域性變數或函式

主要用來提供關於區塊鏈的資訊或一些通用的工具函式。

 

block.blockhash(uint blockNumber) returns (bytes32):指定區塊的區塊雜湊

blockhash(uint blockNumber)

block.coinbase (address): 挖出當前區塊的礦工地址

block.difficulty (uint): 當前區塊難度

block.gaslimit (uint): 當前區塊 gas 限額

block.number (uint): 當前區塊號

block.timestamp (uint): 自 unix epoch 起始當前區塊以秒計的時間戳

gasleft() returns (uint256):剩餘的 gas

msg.data (bytes): 完整的 calldata

msg.gas (uint): 剩餘 gas

msg.sender (address): 訊息傳送者(當前呼叫)

msg.sig (bytes4): calldata 的前 4 位元組(也就是函式識別符號)

msg.value (uint): 隨訊息傳送的 wei 的數量

now (uint): 目前區塊時間戳(block.timestamp)

tx.gasprice (uint): 交易的 gas 價格

tx.origin (address): 交易發起者(完全的呼叫鏈)

 

abi.encode(...) returns (bytes): ABI - 對給定引數進行編碼

abi.encodePacked(...) returns (bytes):對給定引數執行 緊打包編碼

abi.encodeWithSelector(bytes4 selector, ...) returns (bytes): ABI - 對給定引數進行編碼,並以給定的函式選擇器作為起始的 4 位元組資料一起返回

abi.encodeWithSignature(string signature, ...) returns (bytes):等價於 abi.encodeWithSelector(bytes4(keccak256(signature), ...)

 

assert(bool condition):

如果條件不滿足,則使當前交易沒有效果 — 用於檢查內部錯誤。

require(bool condition):

如果條件不滿足則撤銷狀態更改 - 用於檢查由輸入或者外部元件引起的錯誤。

require(bool condition, string message):

如果條件不滿足則撤銷狀態更改 - 用於檢查由輸入或者外部元件引起的錯誤,可以同時提供一個錯誤訊息。

revert():

終止執行並撤銷狀態更改。

revert(string reason):

終止執行並撤銷狀態更改,可以同時提供一個解釋性的字串。

 

addmod(uint x, uint y, uint k) returns (uint):

計算 (x + y) % k,加法會在任意精度下執行,並且加法的結果即使超過 2**256 也不會被擷取。從 0.5.0 版本的編譯器開始會加入對 k != 0 的校驗(assert)。

mulmod(uint x, uint y, uint k) returns (uint):

計算 (x * y) % k,乘法會在任意精度下執行,並且乘法的結果即使超過 2**256 也不會被擷取。從 0.5.0 版本的編譯器開始會加入對 k != 0 的校驗(assert)。

keccak256(...) returns (bytes32):

計算 (tightly packed) arguments 的 Ethereum-SHA-3 Keccak-256)雜湊。

sha256(...) returns (bytes32):

計算 (tightly packed) arguments 的 SHA-256 雜湊。

sha3(...) returns (bytes32):

等價於 keccak256

ripemd160(...) returns (bytes20):

計算 (tightly packed) arguments 的 RIPEMD-160 雜湊。

ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address) 

利用橢圓曲線簽名恢復與公鑰相關的地址,錯誤返回零值。 (example usage)

 

<address>.balance (uint256):

以 Wei 為單位的 地址型別 的餘額。

<address>.transfer(uint256 amount):

地址型別 傳送數量為 amount 的 Wei,失敗時丟擲異常,傳送 2300 gas 的礦工費,不可調節。

<address>.send(uint256 amount) returns (bool):

地址型別 傳送數量為 amount 的 Wei,失敗時返回 false,傳送 2300 gas 的礦工費用,不可調節。

<address>.call(...) returns (bool):

發出低階函式 CALL,失敗時返回 false,傳送所有可用 gas,可調節。

<address>.callcode(...) returns (bool):

發出低階函式 CALLCODE,失敗時返回 false,傳送所有可用 gas,可調節。

<address>.delegatecall(...) returns (bool):

發出低階函式 DELEGATECALL,失敗時返回 false,傳送所有可用 gas,可調節。

 

this (current contract's type):

當前合約,可以明確轉換為 地址型別

selfdestruct(address recipient):

銷燬合約,並把餘額傳送到指定 地址型別

suicide(address recipient):

與 selfdestruct 等價,但已不推薦使用。

1.2.42. 控制結構

Solidity 中有 if,else,while,do,for,break,continue,return,? :

1.2.43. 呼叫函式時指定gasvalue

InfoFeed feed;

feed.info.value(10).gas(800)();

當呼叫其他合約的函式時,隨函式呼叫傳送的 wei gas 的數量可以分別由特定選項 .value() (前提是被調方法有用payable修飾)和 .gas() 指定:

1.2.44. 具名呼叫

function f(uint key, uint value) public {

f({value: 2, key: 3});

1.2.45. 未使用的引數的名稱可省略

function func(uint k, uint) public pure returns(uint) {

    return k;

}

1.2.46. 可見性

external :

外部函式作為合約介面的一部分,意味著我們可以從其他合約和交易中呼叫。 一個外部函式 f 不能從內部呼叫(即 f 不起作用,但 this.f() 可以)。 當收到大量資料的時候,外部函式有時候會更有效率。

public :

public 函式是合約介面的一部分,可以在內部或通過訊息呼叫。對於公共狀態變數, 會自動生成一個 getter 函式(。

internal :

這些函式和狀態變數只能是內部訪問(即從當前合約內部或從它派生的合約訪問),不使用 this 呼叫。

private :

private 函式和狀態變數僅在當前定義它們的合約中使用,並且不能被派生合約使用。

1.2.47. 合約繼承

contract mortal is owned {

 

支援多繼承:

contract Register is priced, owned {

 

如果建構函式接受引數,則需要在宣告(合約的建構函式)時提供,

contract PriceFeed is owned, mortal, named("GoldFeed") {

 

修飾器(modifier) 是合約的可繼承屬性, 並可能被派生合約覆蓋。

1.2.48. constant狀態變數

狀態變數可以被宣告為 constant。在這種情況下,只能使用那些在編譯時有確定值的表示式來給它們賦值。 任何通過訪問 storage,區塊鏈資料(例如 now, this.balance 或者 block.number)或執行資料( msg.gas 或對外部合約的呼叫來給它們賦值都是不允許的。 在記憶體分配上有邊界效應(side-effect)的表示式是允許的,但對其他記憶體物件產生邊界效應的表示式則不行。 內建(built-in)函式 keccak256,sha256,ripemd160,ecrecover,addmod 和 mulmod 是允許的(即使他們確實會呼叫外部合約)。

 

ActionChoices constant defaultChoice = ActionChoices.GoStraight; 

constant 修飾狀態變數時:不允許賦值(除初始化以外)

1.2.49. view修飾函式

function winningProposal() public view

            returns (uint winningProposal_)

view 修飾函式時不允許修改狀態,但當前不是強制的。

constant 修飾函式時與 view 等價。

 

可以將函式宣告為 view 型別,這種情況下要保證不修改狀態。

下面的語句被認為是修改狀態:

  1. 修改狀態變數。
  2. 產生事件
  3. 建立其它合約
  4. 使用 selfdestruct。
  5. 通過呼叫傳送以太幣。
  6. 呼叫任何沒有標記為 view 或者 pure 的函式。
  7. 使用低階呼叫。
  8. 使用包含特定操作碼的內聯彙編。

1.2.50. pure修飾函式

函式可以宣告為 pure ,在這種情況下,承諾不讀取或修改狀態。

 

pure 修飾函式時不允許修改或訪問狀態,當前不強制。

以下被認為是從狀態中讀取:

  1. 讀取狀態變數。
  2. 訪問 this.balance 或者 <address>.balance。
  3. 訪問 block,tx, msg 中任意成員 (除 msg.sig 和 msg.data 之外)。
  4. 呼叫任何未標記為 pure 的函式。
  5. 使用包含某些操作碼的內聯彙編。

1.2.51. fallback函式

合約可以有一個未命名的函式。這個函式不能有引數也不能有返回值。 如果在一個到合約的呼叫中,沒有其他函式與給定的函式識別符號匹配(或沒有提供呼叫資料),那麼這個函式(fallback 函式)會被執行。

 

1.2.52. 函式支援過載

合約可以具有多個不同引數的同名函式。這也適用於繼承函式。

1.2.53. 介面

interface Token {

    function transfer(address recipient, uint amount) public;

}

1.2.54. 內聯彙編

1.3. 參考資料

https://solidity.readthedocs.io/en/v0.5.0/

https://solidity-cn.readthedocs.io/zh/develop/abi-spec.html

https://github.com/ethereum/ethereumj