Solidity學習 - 錯誤處理

文章目錄

    • 前言
    • EVM錯誤處理機制
      • EVM錯誤處理的核心特性
      • 程序中的錯誤處理
    • 錯誤拋出方法
      • require()函數
        • require()觸發異常的場景
        • 關鍵特性
      • assert()函數
        • assert()觸發異常的場景
        • 關鍵特性
      • require() vs assert():選擇指南
      • revert()函數
        • 關鍵特性
    • 異常捕獲:try/catch
      • 外部調用異常捕獲
      • 高級異常捕獲
      • 注意事項

前言

在Solidity智能合約開發中,錯誤處理是保障合約安全和可靠性的重要環節。與傳統編程語言不同,EVM(以太坊虛擬機)的錯誤處理機制具有獨特的特性,本文將詳細介紹Solidity中錯誤處理的核心概念、方法及最佳實踐。

EVM錯誤處理機制

EVM錯誤處理的核心特性

EVM的錯誤處理機制與Java、JavaScript等傳統語言有本質區別:當EVM執行過程中遇到錯誤(如數組越界、除零操作等),會觸發交易回退(revert),導致整個交易的狀態變更被撤銷。這種機制確保了以太坊交易的原子性——所有操作要么全部成功,要么全部失敗,不會出現部分狀態修改的情況。

傳統語言錯誤處理 vs EVM錯誤處理
┌──────────────┐     ┌──────────────┐
│ 開始執行      │     │ 開始執行      │
│              │     │              │
│ 操作1 生效    │     │ 操作1 生效    │
│              │     │              │
│ 發生錯誤      │     │ 發生錯誤      │
│              │     │              │
│ 操作2 未執行  │     │ 回退到初始狀態 │
│              │     │              │
└──────────────┘     └──────────────┘

程序中的錯誤處理

在合約代碼中,錯誤處理主要通過條件檢查、錯誤拋出和異常捕獲來實現。無論主動拋出錯誤還是遇到未處理的情況,EVM都會回滾交易。以下是Solidity中錯誤處理的核心方法:

錯誤拋出方法

Solidity提供了三種拋出異常的方式:require()assert()revert(),每種方式適用于不同的場景。

require()函數

require()函數用于在執行邏輯前檢查輸入參數或合約狀態是否滿足條件,不滿足時拋出異常并回滾交易。

pragma solidity >=0.8.0;
contract testRequire {function vote(uint age) public {require(age >= 18, "只有18歲以上才可以投票");// 投票邏輯...}function transferOwnership(address newOwner) public {require(owner() == msg.sender, "調用者不是Owner");// 所有權轉移邏輯...}
}
require()觸發異常的場景
  • 消息調用的函數未正確結束(耗盡gas、無匹配函數或自身拋出異常)
  • 使用new關鍵字創建合約失敗
  • 調用不存在的外部函數
  • 向不可接收ETH的合約轉賬或調用無payable修飾符的函數
關鍵特性
  • 觸發REVERT操作碼回滾交易
  • 未使用的Gas返回給交易發起者
  • 適用于檢查用戶輸入、外部調用返回值和合約狀態

assert()函數

assert()函數用于檢查內部邏輯的正確性,假設條件始終為真,否則表示程序出現未知錯誤。

pragma solidity >=0.8.0;
contract testAssert {bool public inited;function checkInitValue() internal {// 假設inited永遠為falseassert(!inited);// 其他邏輯...}
}
assert()觸發異常的場景
  • 數組或固定長度bytesN索引越界
  • 除零或模零運算
  • 負數位移
  • 枚舉類型轉換錯誤
  • 調用未初始化的內部函數類型變量
關鍵特性
  • 在Solidity 0.8.0及以上版本觸發REVERT操作碼
  • 適用于檢查溢出錯誤和不應該發生的異常情況
  • 可被分析工具(如STMChecker)用于錯誤檢測

require() vs assert():選擇指南

場景優先使用require()優先使用assert()
檢查用戶輸入??
檢查外部調用返回值??
檢查合約狀態??
函數開頭條件檢查??
檢查溢出錯誤??
檢查不應該發生的情況??
函數中間/結尾檢查??

revert()函數

revert()函數用于顯式回退交易,支持自定義錯誤和錯誤消息。

pragma solidity ^0.8.4;
contract testRevert {address public owner;error NotOwner(); // 自定義錯誤function transferOwnership(address newOwner) public {if (owner != msg.sender) revert NotOwner();owner = newOwner;}
}
關鍵特性
  • 兩種形式:revert CustomError(arg1, arg2)revert(string memory reason)
  • 自定義錯誤(如error NotOwner())消耗Gas更低(僅4字節編碼)
  • 功能與require()等價,但提供更靈活的錯誤處理方式

異常捕獲:try/catch

外部調用異常捕獲

通過try/catch可以捕獲外部調用的異常,避免交易因外部合約錯誤而回退。

contract CalledContract {function getTwo() external returns (uint256) {return 2;}
}contract TryCatcher {CalledContract public externalContract;function executeEx() public returns (uint256, bool) {try externalContract.getTwo() returns (uint256 v) {uint256 newValue = v + 2;return (newValue, true);} catch {// 處理異常}}
}

高級異常捕獲

catch支持不同子句捕獲不同類型的異常:

contract TryCatcher {event ReturnDataEvent(bytes someData);event CatchStringEvent(string someString);event SuccessEvent();function execute() public {try externalContract.someFunction() {emit SuccessEvent();} catch Error(string memory revertReason) {emit CatchStringEvent(revertReason); // 捕獲require/revert的字符串錯誤} catch (bytes memory returnData) {emit ReturnDataEvent(returnData); // 捕獲其他類型異常}}
}

注意事項

  • try/catch僅適用于捕獲外部調用的異常,無法捕獲內部代碼異常
  • 本地變量僅在trycatch塊內有效
  • 錯誤提示轉換為bytes失敗時,try/catch會回退整個交易

想要了解更詳細的內容,可以訪問錯誤處理。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912229.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912229.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912229.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何永久刪除Android上的短信[無法恢復]

當您不再保留 Android 設備時,您將需要徹底刪除所有私人數據,包括短信。因此,有必要了解如何永久刪除Android上的短信。現在,閱讀本指南,掌握消除信息的實用方法。 第 1 部分:如何一鍵永久刪除 Android 上的…

P12894 [藍橋杯 2025 國 Java B] 智能交通信號燈

[Problem] \color{blue}{\texttt{[Problem]}} [Problem] 給定一個長度為 n n n 的數組 a 1 … n a_{1\dots n} a1…n?&#xff0c;進行 m m m 次一下操作&#xff1a; 給定 l , r l,r l,r&#xff0c;求出 ∑ l ≤ i < j ≤ r mex { a i , a j } \sum\limits_{l \le…

華為云Flexus+DeepSeek征文|基于華為云一鍵部署的 Dify-LLM 平臺構建智能試卷生成助手

目錄 前言 1 華為云Dify-LLM應用平臺部署 1.1 一鍵部署平臺簡介 1.2 四步完成部署流程 2 接入華為云 DeepSeek 自定義大模型 2.1 ModelArts Studio 模型服務介紹 2.2 配置自定義大模型 3 創建試卷生成工具&#xff08;工作流&#xff09; 3.1 設計 DSL 工作流 3.2 工…

嵌入式硬件與應用篇---寄存器GPIO控制

在 ARM 架構中&#xff0c;通過 32 位寄存器控制 GPIO&#xff08;通用輸入輸出&#xff09;的核心步驟和方法可分為以下幾個關鍵環節&#xff0c;結合不同芯片的實現差異&#xff0c;具體操作需參考對應的數據手冊&#xff1a; 一、GPIO 控制的核心步驟 1. 使能 GPIO 時鐘 …

Fiddler中文版抓包工具在跨域與OAuth調試中的深度應用

跨域和OAuth授權流程一直是Web和移動開發中最容易踩坑的領域。復雜的CORS配置、重定向中的Token傳遞、授權碼流程的跳轉&#xff0c;以及多域名環境下的Cookie共享&#xff0c;常常讓開發者陷入調試困境。此時&#xff0c;一款能夠精準捕獲、修改、重放請求的抓包工具顯得至關重…

React用戶交互事件

在React中處理用戶交互事件&#xff08;如點擊、輸入、提交等&#xff09;的方式與原生JavaScript類似&#xff0c;但有一些語法差異和最佳實踐。以下是常見交互事件的處理方法及代碼示例&#xff1a; 一、基本事件處理&#xff08;點擊、輸入等&#xff09; 1. 點擊事件&…

DHT11 STM32 HAL驅動庫 整數

dht11.h #ifndef __DHT11_H #define __DHT11_H#include "stm32f1xx_hal.h" // 根據實際芯片型號調整&#xff08;如stm32f4xx_hal.h&#xff09;// DHT11數據結構 typedef struct {GPIO_TypeDef *GPIOx; // GPIO端口&#xff08;如GPIOA&#xff09;uint16_t GP…

【Actix Web 精要】Rust Web 服務開發核心技術與實戰指南

目錄 一、Actix Web 核心架構解析1.1 核心組件交互流程1.2 關鍵組件說明&#xff1a; 二、項目初始化與配置2.1 創建項目2.2 添加依賴 (Cargo.toml)2.3 項目結構 三、核心模塊實現3.1 配置管理 (src/config.rs)3.2 應用狀態管理 (src/main.rs)3.3 數據模型 (src/models/user.rs…

從URL到視頻:用Python和AI構建自動化內容講解視頻生成管道

摘要 本文旨在從技術層面&#xff0c;深入探討并實踐一個將任意網頁鏈接&#xff08;如飛書文檔、博客文章&#xff09;自動轉換為帶有配音和字幕的講解視頻的系統。我們將詳細拆解整個實現流程&#xff0c;覆蓋從內容抓取與解析、利用大語言模型&#xff08;LLM&#xff09;智…

Java 使用 Easy Excel 進行 Excel 數據導入導出

1. 通過 Maven 下載 Easy Excel 依賴包 在項目的 pom.xml 文件中添加以下依賴&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version> <!-- 使用最新版本 -->…

國產化條碼類庫Spire.Barcode教程:如何使用 C# 讀取 PDF 中的條碼(兩種方法輕松實現)

在 PDF 文檔的 .NET 平臺處理流程中&#xff0c;使用 C# 讀取 PDF 條碼 是一項常見需求&#xff0c;特別適用于處理掃描件或電子表單。無論是物流、金融、醫療還是制造行業&#xff0c;PDF 文檔中經常包含用于追蹤或識別的條碼。這些條碼可能是嵌入圖像&#xff0c;也可能是矢量…

2023國賽數字取證-流量分析

數據取證 - 1 A 集團的?絡安全監控系統發現惡意份?正在實施?級可持續攻擊&#xff08;APT&#xff09;&#xff0c;并抓取了部分可疑流量包。請 您根據捕捉到的流量包&#xff0c;搜尋出?絡攻擊線索&#xff0c;分解出隱藏的惡意程序&#xff0c;并分析惡意程序的?為。 …

【預約小程序】-健身房預約課程小程序——仙盟創夢IDE

東方仙盟-坐擁萬個代碼 免費報表 阿雪技術觀 讓我們積極投身于技術共享的浪潮中&#xff0c;不僅僅是作為受益者&#xff0c;更要成為貢獻者。無論是分享自己的代碼、撰寫技術博客&#xff0c;還是參與開源項目的維護和改進&#xff0c;每一個小小的舉動都可能成為推動技術進…

SmartETL中數據庫操作與流程解耦的設計與應用

正如ETL這個概念本身所指示的&#xff0c;數據庫讀寫訪問是ETL的最常用甚至是最主要的操作。現代信息系統的設計與運行基本都是圍繞數據庫展開的&#xff0c;很多應用的核心功能都是對數據庫的CRUD&#xff08;創建、檢索、更新、刪除&#xff09;操作。 SmartETL框架設計之初…

【記錄解決問題】activiti--sql 轉義符設置

一、背景 %、&#xff01;、_在sql查詢時需要轉義&#xff0c;轉義的語法 like %?2% escape ?#{escapeCharacter()}二、activiti轉義配置 String wildcardEscapeClause ""; if (this.databaseWildcardEscapeCharacter ! null && this.databaseWildcard…

Unity AR構建維護系統的以AI驅動增強現實知識檢索系統

本博客概述了為維護開發的AI驅動增強現實&#xff08;AR&#xff09;知識檢索系統的開發過程&#xff0c;該系統集成了Unity用于AR、Python服務器用于后端處理&#xff0c;以及ChatGPT用于自然語言處理。該系統允許維護工人通過AR設備&#xff08;如HoloLens 2&#xff09;查詢…

Java面向對象核心:方法值傳遞與封裝機制精講

文章目錄 Java面向對象編程核心筆記一、方法值傳遞機制1. 基本數據類型傳遞2. 引用數據類型傳遞值傳遞總結 二、面向對象核心概念1. 類與對象關系2. 類定義規范3. 對象創建與使用 三、封裝機制詳解1. 封裝三大要素2. 封裝示例&#xff08;GirlFriend類&#xff09;3. 測試類4. …

【Actix Web】構建高性能 Rust API:Actix Web 最佳實踐與進階指南

目錄 一、高性能 API 架構設計1.1 系統架構圖1.2 核心組件 二、項目初始化與配置2.1 創建項目2.2 添加依賴 (Cargo.toml)2.3 配置文件 (config/default.toml) 三、核心模塊實現3.1 應用狀態管理 (src/state.rs)3.2 數據模型定義 (src/models.rs) 四、認證與授權系統4.1 JWT 認證…

vue項目中純前端實現導出pdf文件,不需要后端處理。

在 Vue 項目中&#xff0c;純前端實現導出 PDF 文件是完全可行的。通常可以借助一些 JavaScript 庫來將 HTML 內容或 DOM 元素轉換為 PDF 并下載&#xff0c;無需后端參與。 下面介紹幾種常用的方案和實現方法&#xff1a; 推薦方案&#xff1a;使用 html2canvas jsPDF 安裝…

c++虛擬內存

常見的內存困惑 當你編寫C程序時&#xff0c;是否遇到過&#xff1a; vector申請200MB內存&#xff0c;但系統顯示只占用20MB&#xff1f;程序在低配機器上崩潰&#xff0c;報出std::bad_alloc但內存顯示充裕&#xff1f;遍歷數組時特定位置耗時突然增加&#xff1f;相同代碼…