進入Cloud IDE開發環境
可通過以下任一方式進入 Cloud IDE 合約開發環境:
在BaaS 平臺BaaS 平臺,單擊螞蟻區塊鏈 > 合約鏈,單擊目標鏈操作欄下的管理,單擊左側導航欄上的合約工程管理。在合約工程管理頁,您可以通過創建合約工程或編輯已有的合約,進入 Cloud IDE 合約開發環境。
您也可以單擊螞蟻區塊鏈 > 概覽頁面的合約體驗鏈卡片上的調試合約,進入Cloud IDE開發環境。
Cloud IDE 合約工程管理
可以通過Cloud IDE對合約工程內的文件夾、文件進行 新建、刪除、修改名字 操作。
在 Cloud IDE 的左側導航欄中,第一個功能模塊就是合約工程管理。在該模塊,您可以對合約工程內的文件夾、文件進行新建、刪除、重命名等操作。
添加文件夾。
添加文件,如果是 Solidity 合約文件,需要以
.sol
為擴展名。拖拽、移動文件或文件夾。
刪除文件或文件夾。
您也可單擊根目錄的下載圖標,將整個文件夾壓縮下載至本地。
從合約工程管理頁面進入Cloud IDE,默認實時保存文件。
當前Cloud IDE僅支持對Solidity合約進行編譯,新增合約文件請以
.sol
結尾,否則編譯失敗。
Cloud IDE 合約開發流程
使用 Cloud IDE 開發合約的過程主要分為以下 5 步:
選擇目標合約鏈
在Cloud IDE中,單擊左上角的鏈名稱進入環境配置,選擇目標的合約鏈環境。
在環境配置中,您可以選擇自己已有的鏈配置環境。例如,您已申請體驗鏈,則可以選擇已有的公共 合約鏈,該體驗鏈會配備一個默認的測試賬戶,您可以直接用來部署、調用合約。如果此測試賬戶不能滿足需求,您也可以使用通過 SDK 創建的賬戶,但是需要填入私鑰(16 進制字符串),因為在部署、調用合約時IDE都需要賬戶的私鑰對交易做簽名處理。
關于如何獲取 16 進制字符串形式的私鑰,參見準備合約鏈的賬戶中的示例代碼。
編譯合約
開發合約過程中,可以隨時對已完成的代碼進行編譯。
在 Cloud IDE 中,點擊 編譯,開始編譯代碼。
字節碼即合約代碼的編譯結果,也是合約部署時使用的關鍵數據,通過 SDK 可以將合約字節碼部署到目標的生產鏈上使用。
合約接口說明(ABI)應用程序二進制接口(Application Binary Interface,ABI)可以理解為合約的接口說明。當合約被編譯后,其對應的 ABI 也會一起生成。
ABI 類似于程序中的接口說明文檔,描述了屬性和方法簽名相關信息,包括字段名稱、字段類型、方法名稱、參數名稱、參數類型、方法返回值類型等。
ABI 參數說明:
參數 | 說明 |
name | 函數名稱 |
type | 方法類型,包括 function、constructor、fallback(缺省方法),默認為 function。 |
constant | 布爾值,如果為 true,則表示方法不會修改合約字段的狀態變量。 |
payable | 布爾值,表示方法是否可以接收系統轉賬。 |
stateMutability | 狀態類型,包括 pure(不讀取區塊鏈狀態)、view(和 constant 類型一樣,只能查看,不會修改合約字段)、nonpayable(和 payable 含義一樣)、payable(和 payable 含義一樣)。 |
inputs | 數組,描述參數的名稱和類型。 |
name | 參數名稱 |
type | 參數類型 |
outputs | 和 inputs 一樣,如果沒有返回值,缺省是一個空數組。 |
更多 ABI 相關信息,參見 Solidity ABI 官方介紹(英文)。
部署合約
合約編譯通過后,單擊左側導航欄上的部署圖標,即可查看編譯后得到的字節碼和ABI文件。在 Cloud IDE 中單擊部署合約,將合約部署到目標體驗鏈進行測試。
在部署定義了 constructor
方法的合約時,需要給定 constructor
方法的參數。Cloud IDE 支持合約方法參數類型的提示和一些基本數據類型的初始化賦值,您可根據自身實際情況初始化合約。
部署成功后,可以看到合約的所有方法列表。
調用合約
合約部署成功后,IDE 會列出合約中所有的 public 方法以及 public 類型的狀態變量。點擊目標方法右側的 調用合約 進行調用。
其中,狀態變量對應的調用可以直接返回當前狀態變量的值。合約方法的調用可以返回如下幾個字段:
參數 | 說明 |
input | 合約方法的輸入數據,通常為合約方法的參數。 |
output | 合約方法的返回值,可能是多個值,根據返回值具體類型轉碼顯示。 |
log | 如果在合約中使用了 Event 事件,并且事件被觸發,則會在 log 中展示。 |
錯誤說明
在使用 Cloud IDE 過程中,可能遇到一些錯誤提示。在調用合約時,如果合約執行過程中出錯,可能有多種原因,Cloud IDE 會將合約調用失敗的錯誤碼信息返回,便于您分析原因。Cloud IDE 使用的錯誤碼信息與 SDK 使用的錯誤碼保持一致,您可以查看 合約鏈錯誤碼找到對應的錯誤碼說明。
下面通過一個錯誤碼示例來說明如何通過錯誤說明的提示分析合約內部錯誤的原因,您也可以通過添加 Event 事件的方式來調試合約。
錯誤碼示例:
在上圖的錯誤碼示例中,系統調用了 Cloud IDE 示例合約的 voteForCandidate
方法,給定的候選人為Demi
,返回的錯誤碼為10201
,其含義為:
錯誤碼 | 錯誤碼值 | 描述 |
VM_REVERT | 10201 | 觸發 revert 指令導致的錯誤 |
根據錯誤碼提示,可以判斷調用合約失敗是因為觸發了 revert
語句,含義為某個 require()
方法判斷失敗。查看合約代碼,即可發現 voteForCandidate
方法中的相關條件檢查:
require(validCandidate(candidate));
由此,可推斷出輸入的候選人 Demi
不合法,并不在實際投票的候選人列表 candidateList
中。事實也確實如此,合約部署過程中,constructor
參數僅指定了 Nick
和 Rose
兩個候選人參與競選。
調試合約
目前,您可以通過添加 Event
事件觸發日志的方式實現邏輯分支的判斷和分析,進而對合約內部邏輯進行調試。
這里選擇調用合約方法 validCandidate
。
// This function will help to check whether target candidate is in the candidateList.
function validCandidate(bytes32 candidate) view public returns (bool) {
for (uint i = 0; i < candidateList.length; i++) {
if (candidateList[i] == candidate) {
emit VALID(true);
return true;
}
}
emit VALID(false);
return false;
}
在 validCandidate
方法的實現中,不同的執行邏輯會根據情況觸發不同的 Event
事件,通過查看調用結果日志信息,即可分析出合約的執行路徑。在以上示例中,執行邏輯相對簡單。在復雜的邏輯控制方法中,通過添加 Event
事件的方式可以很好的追蹤合約執行路徑,達到調試合約的目的。
合約單步調試
合約調試模塊增加了一個虛擬機模擬器,可以模擬運行 Solidity 合約并給出執行結果。當前虛擬機模擬器與真實合約鏈有一些差異,主要差異在于虛擬機模擬器暫時不支持對 JSON/XML 的解析,將在后續功能升級中提供支持。
通常,對一個交易的 Debug 過程如下:
編譯并部署合約到虛擬機模擬器中。
下圖示例中,部署創建工程時默認添加的 demo 樣例合約,部署時初始化了兩個候選人“Demi”和“Rose”:
調用要調試的目標合約方法,產生執行的交易 hash。
下圖示例中,調用默認 demo 樣例的方法
voteForCandidate
:在底部調試詳情信息欄,可單擊調試按鈕直接調試步驟 2 產生的目標交易。
可以單步單擊圖示中的箭頭按鈕,進行單步調試,同時查看運行時的局部變量、合約存儲狀態、堆棧、內存等關鍵信息進行深入調試。
合約單元測試
Cloud IDE 支持編寫單元測試用例,所有的測試用例文件規定存放在 test
目錄下,便于管理。
當前,IDE 支持使用 Solidity 語言編寫單元測試。IDE 提供了便于編寫測試用例的 Asset 庫方法和測試賬戶。
為方便使用,在 IDE 單元測試模塊中單擊添加測試文件,可以快速生成一個單元測試用例,并且生成后的測試用例可以直接運行:
創建合約工程時,默認添加了一個 demo 合約,針對這個 demo 合約的單元測試用例如下:
pragma solidity ^0.4.20;
import "ide_tests.sol"; // the import is automatically injected by IDE.
import "../demo.sol"; // the path of target contract to test.
contract test_vote {
Voting voteToTest; // the target testing contract
function beforeAll () public {
bytes32[] params;
params.push(bytes32(1));
voteToTest = new Voting(params);
Assert.equal(voteToTest.totalVotes(), uint(0), "0 should be the total votes");
}
function checkTotalVotes () public {
Assert.equal(voteToTest.validCandidate(bytes32(1)), true, "should be a valid candidate");
voteToTest.voteForCandidate(bytes32(1));
Assert.equal(voteToTest.totalVotes(), uint(1), "1 should be the total votes");
}
}
運行此單元測試的結果為:
引入目標測試合約
單元測試的核心目標是測試一個目標合約,因此在單元測試中要引入需要測試的合約(
import "../demo.sol";
),然后創建并初始化此目標合約(voteToTest = new Voting(params);
),進而調用此目標合約的方法進行測試。Asset 庫支持
其中
import "ide_tests.sol"
是 Cloud IDE 提供的 Asset 庫,核心提供了不同合約數據類型的equal
、notEqual
、greaterThan
、lesserThan
、ok
等方法。如果代碼中沒有顯式的引入ide_tests.sol
文件,Cloud IDE 也會自動注入此依賴庫,方便您使用。在使用 Asset 的比較方法時,有以下注意事項:
類型 identity 的對比要使用
equalID
和notEqualID
方法。Asset 庫中沒有提供 uint8 ~ uint128 以及 int8 ~ int128 的對比方法,這些數據類型的比較都可以通過轉換為 uint 和 int 進行,例如
Assert.equal(uint(2), uint(1), "error message defined by case");
。除此之外,Asset 庫還提供一些單元測試執行前后的處理方法:
beforeAll
、beforeEach
、afterAll
、afterEach
,可以根據具體需求或場景使用。
TestsAccounts
測試賬戶在某些特殊場景下,需要指定合約的調用方(sender),比如測試角色權限控制,特定的角色才能調用某些合約方法。
在測試用例運行前,IDE 會默認隨機創建 3 個測試賬戶以供使用,這 3 個賬戶的 ID 隨機生成,并不固定。在編寫測試用例方法時,可以通過寫注釋的方式指定賬戶,這樣調用此用例方法時就會使用指定的賬戶來簽名交易。例如以下使用方式:
/// sender: account-0 function checkSenderIsAccount0 () public { // the commits 'sender: account-0' says to use 'TestsAccounts.getAccount(0)' as sender. Assert.equalID(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIsAccount0"); }
其中
/// sender: account-0
注釋非常關鍵,指定了使用 IDE 生成的 3 個賬戶中的第一個account-0
來調用方法checkSenderIsAccount0
進行測試。在代碼中對應獲取account-0
的方式是:TestsAccounts.getAccount(0)
。同樣,如果需要使用其他兩個賬戶,只需指定為
/// sender: account-1
或/// sender: account-2
即可。重要需要引入
import "ide_accounts.sol";
。