| Chapter 9 | 異常處理 Handling Exception

面對異常處理,我們得先簡單理解交易以及錯誤(Transactions and Errors),並且條列一些在Solidity中異常處理的性質。

  • 交易是自動化的,一旦送出便沒有辦法在過程中透過人為終止

  • 拋出Errors是會回復狀態的行為,並不會讓錯誤發生。

  • 語法包含 require, assert, revert,在更早的版本還有throw;

  • 除了以下 Low-Level 的函數以外,皆為接連發生的(cascade)

    • Address.send, address.call, address.delegatecall, address.staticcall

  • Revertrequire 可以回傳錯誤訊息

0.4.10 版的 Solidity 新增了 require(), assert(), revert() 這三個語法

  • require() 用來檢查較不嚴重的錯誤,通常是在執行前就檢驗合理的輸入或條件,可以退回為使用到的 gas

  • assert() 用來檢查較嚴重的錯誤,會像以前一樣拿走所有的 gasLimit 的手續費

  • revert()require() 基本上相同,但是 revert() 沒有包括狀態檢查

0.6 之後新增了 try/catch 可以使用

pragma solidity ^0.8.11;

contract Exception{
    
    mapping(address => uint64) public balanceReveived;
    
    function receiveMoney() public payable {
        assert(balanceReceived[msg.sender] + uint64(msg.value) >= balanceReceived[msg.sender])
        balanceReveived[msg.sender] += uint64(msg.value);
    }
    
    function withdrawMoney(address payable _to, uint64 _amount) public {
        require(balanceReceived[msg.sender] <= _amount, "You don't have enough ether");
        assert(balanceReceived[msg.sender] >= balanceReceived[msg.sender] - _amount)
        balanceReceived[msg.sender] -= _amount;
        _to.transfer(_amount);
    }
}

以上例子之中我們可以發現:

  • 在加上 assert 之前,當我們想要匯入10ethers兩次,實際上合約不會收到20ethers,原因是來自於uint64

  • 在我們加上 assert 之後,當我們想要匯入10ethers兩次,便會在第二次動作時接收到回傳的錯誤。

Throw

  • 於Solidity 0.4.10版本後移除

if (msg.sender != owner) {
    throw;
}

Last updated