Solidity 智能合約調試與扁平化:使用 Remix IDE 和 Truffle 本文介紹如何使用 Remix IDE 調試 Solidity 智能合約,以及使用 Truffle Flattener 扁平化合約代碼以方便調試和驗證。 關鍵要點: 合約扁平化: 將多個 Solidity 文件合併成一個文件,去除 import 語句,方便人工審查、Etherscan 驗證和 Remix IDE 調試(Remix IDE 目前不支持 import)。 Remix IDE: 功能強大的 Solidity IDE,擁有優秀的逐步調試器,支持時間回溯、步驟切換、局部變量和狀態探索、斷點設置等功能。 Truffle 和 OpenZeppelin: 用於構建自定義 Token 的工具。 Truffle Flattener 是一個 npm 工具,用於扁平化 Truffle 項目中的 Solidity 文件及其依賴項。 Remix IDE 調試方法: 根據用例的不同,有兩種調試方法。可以通過引入錯誤來測試調試器功能,並使用 SafeMath 的 assert() 函數來強制規則並識別合約中的問題。 在以太坊主網上,智能合約使用真金白銀,因此構建無錯誤的智能合約至關重要,需要使用調試器等專用工具。 Remix IDE 是功能最全面的 Solidity IDE,它擁有一個出色的逐步調試器。您可以執行各種任務,例如:時間回溯、更改當前步驟、通過展開各種面板來探索局部變量和當前狀態,以及設置斷點以在代碼的不同點之間移動。您還可以使用終端顯示從 Remix 執行的交易並對其進行調試。 本教程將使用 Truffle 和 OpenZeppelin 構建一個簡單的自定義 Token,解釋為什麼以及如何扁平化合約,最後使用 Remix IDE 開始調試合約。 為什麼扁平化智能合約? 合約扁平化是指將所有 Solidity 代碼合併到一個文件中,而不是多個源文件中,這樣,就不需要 import 語句,導入的代碼會嵌入到同一個文件中。我們需要扁平化智能合約的原因有很多,例如:手動審查合約、在 Etherscan 上驗證合約或使用 Remix IDE 調試合約(因為它目前不支持 import)。 使用 Truffle 和 OpenZeppelin 編寫簡單的 Token Remix IDE 官方推薦用於構建小型合約或學習 Solidity,但是當您需要構建更大的合約或需要高級編譯選項時,您必須使用 Solidity 編譯器或其他工具/框架,例如 Truffle。 除了無錯誤的合約外,安全性也是構建智能合約的關鍵部分。出於這個原因,使用經過實戰檢驗的框架(如 OpenZeppelin),它提供可重用、經過良好測試和社區審查的智能合約,這將有助於減少您的 DApp 中的漏洞。 讓我們看看如何使用 Truffle 和 OpenZeppelin 創建一個簡單的自定義 Token,它擴展了 OpenZeppelin 的標準 Token。 先決條件 本教程需要您具備 Truffle、以太坊和 Solidity 的一些知識。您可以閱讀區塊鏈入門和以太坊入門教程。 您還需要在系統上安裝 Node.js 5.0 和 npm。請參考其下載頁面了解說明。 安裝 Truffle 使用您的終端,運行以下命令安裝 Truffle: npm install -g truffle登入後複製登入後複製 創建新的 Truffle 項目 首先為您的項目創建一個新目錄。讓我們將其命名為 simpletoken 並導航到其中: mkdir simpletoken cd simpletoken truffle init登入後複製登入後複製 此命令將創建多個文件夾,例如 contracts/ 和 migrations/,以及部署合約到區塊鏈時將使用的文件。 接下來,我們將安裝 OpenZeppelin: npm install openzeppelin-solidity登入後複製登入後複製 創建簡單的 Token 合約 在 contracts/ 文件夾內,創建一個名為 SimpleToken.sol 的文件並添加以下內容: pragma solidity ^0.4.23; import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol'; contract SimpleToken is StandardToken { address public owner; string public name = 'SimpleToken'; string public symbol = 'STt'; uint8 public decimals = 2; uint public INITIAL_SUPPLY = 10000; constructor() public { totalSupply_ = INITIAL_SUPPLY; balances[owner] = INITIAL_SUPPLY; } }登入後複製 這是我們將要扁平化和調試的合約。我們正在導入 OpenZeppelin StandardToken.sol 合約並聲明我們的 SimpleToken 合約,該合約使用 is 運算符擴展 StandardToken.sol。 我們的合約將繼承許多變量和函數,需要覆蓋這些變量和函數才能自定義合約。 為了完成我們的 Truffle 項目,在項目的 migrations/ 文件夾內,創建一個名為 2_deploy_contract.js 的文件並添加以下內容: var SimpleToken = artifacts.require("SimpleToken"); module.exports = function(deployer) { deployer.deploy(SimpleToken); };登入後複製 使用此文件,我們可以將智能合約部署/遷移到區塊鏈中,但對於此示例,我們實際上不需要此文件,因為我們將使用 Remix IDE 在扁平化後部署智能合約。 使用 Truffle Flattener 扁平化合約 Truffle Flattener 是一個 npm 實用程序,它可以按照正確的順序扁平化或組合在 Truffle 下開發的 Solidity 文件及其所有依賴項。 首先,使用以下命令從 npm 全局安裝 truffle-flattener: npm install -g truffle-flattener登入後複製 接下來,在您的 Truffle 項目中,運行以下命令來扁平化 SimpleToken.sol 文件: truffle-flattener contracts/SimpleToken.sol > FlattenedSimpleToken.sol登入後複製 truffle-flattener 將扁平化的合約輸出到標準輸出或終端。使用 > 運算符,我們將輸出保存到當前文件夾中的 FlattenedSimpleToken.sol 文件中。 使用 Remix IDE 編譯和部署合約您可以從 FlattenedSimpleToken.sol 文件訪問扁平化的智能合約。打開該文件並複制其內容。 接下來,從 https://www.php.cn/link/54af6860114f54728b5c2fd9b5cfeca9 打開 Remix IDE,並將扁平化的智能合約粘貼到 IDE 中的新文件中。 如果出現錯誤提示Mock compiler : Source not found,請確保從設置選項卡> Solidity 版本面板> 選擇新的編譯器版本下拉菜單 中選擇較新的編譯器版本。 如果 自動編譯 已禁用,請單擊 編譯 面板中的 開始編譯 按鈕。 接下來,激活 運行 面板。首先確保您已為環境選擇 JavaScript VM。在第二個框中,從下拉菜單中選擇 SimpleToken 合約,然後單擊下拉菜單下方的紅色 部署 按鈕。 您的合約已部署並在 JavaScript VM 上運行,該 VM 模擬區塊鏈。我們現在可以開始以不同的方式對其進行調試。 調試自定義 Token 合約 為了了解如何調試合約,我們將首先引入一些錯誤。 您可以使用兩種不同的方法在 Remix IDE 中開始調試智能合約,具體取決於用例。 當您第一次部署智能合約或隨後執行任何交易時,一些信息將記錄在終端中,您可以從日誌旁邊的白色 調試 按鈕開始調試它。讓我們看看它的實際操作。 使用 assert() SafeMath 是 OpenZeppelin 用於安全檢查的數學運算庫,這些檢查會拋出錯誤。 sub(a,b) 函數減去兩個數字並返回一個無符號數字。第一個參數應該大於第二個參數,這樣我們才能始終獲得正數。該函數使用 assert() 函數強制執行此規則。這是 sub 函數的代碼: npm install -g truffle登入後複製登入後複製 只要您為a 和b 提供驗證條件b < a 的值,執行就會繼續進行,沒有任何問題,但是一旦您提供b 的值大於a 的值,assert() 函數將拋出一個錯誤,提示: mkdir simpletoken cd simpletoken truffle init登入後複製登入後複製 因此,讓我們在 SimpleToken 合約中添加對 sub() 的調用,其中參數錯誤: npm install openzeppelin-solidity登入後複製登入後複製 如果您重新部署合約,您將在終端中收到無效操作碼錯誤: 單擊 調試 按鈕後,您將進入 調試器 面板,您可以在其中開始調試代碼。 在代碼編輯器中,第一行/指令將被突出顯示,標記我們當前在代碼中的位置。 單擊 單步跳過 按鈕以單步執行代碼。 您也可以使用 跳轉到異常 按鈕直接跳轉到異常。 無論您使用哪種方法,調試器都會將您帶到導致問題的代碼,然後停止。 您可以檢查當前步驟中局部變量的狀態。 Solidity 局部變量 面板顯示與當前上下文關聯的局部變量。 從源代碼和 Solidity 局部變量 中,您可以得出結論,問題的根源與 assert() 方法和 b 的值大於 a 的值有關。 您可以使用 停止調試 按鈕停止調試。 也值得查看調試器的其他面板。 指令 指令 面板顯示被調試合約的字節碼。當前步驟的字節碼將被突出顯示。 Solidity 狀態 Solidity 狀態 面板顯示當前被調試合約的狀態變量。 低級面板 這些面板顯示有關執行的低級信息,例如步驟詳細信息、內存、堆棧和函數的返回值。 結論 在本教程中,我們使用 Truffle 和 OpenZeppelin 構建了一個簡單的 Token,然後使用 truffle-flattener 扁平化自定義合約,並使用 Remix IDE 開始調試合約中的錯誤。 希望這將幫助您大膽地深入逐步調試您自己的合約。請告訴我們您的使用情況! (後續內容,關於扁平化合約和在Remix 中進行調試的常見問題解答,已省略,因為篇幅過長,且與核心內容關係較弱。如有需要,可以單獨提出。)