# Solidity中error关键字使用方法

By [xyyme.eth](https://paragraph.com/@xyyme) · 2022-03-13

---

Solidity 在 0.8.4 版本中推出了 error 关键字，可以像 event 那样定义一个错误类型，[官方文档](https://blog.soliditylang.org/2021/04/21/custom-errors/)提到使用 error 关键字可以节省 gas，并且可以在错误信息中添加参数：

> Starting from [Solidity v0.8.4](https://github.com/ethereum/solidity/releases/tag/v0.8.4), there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., `revert("Insufficient funds.");`), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.

我们直接来看官方的例子

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;
    
    // 定义错误类型
    error Unauthorized();
    
    contract VendingMachine {
        address payable owner = payable(msg.sender);
    
        function withdraw() public {
            if (msg.sender != owner)
                // 抛出异常
                revert Unauthorized();
    
            owner.transfer(address(this).balance);
        }
        // ...
    }
    

可以看到，这种抛出异常的方法和 event 几乎一模一样：

*   event 变成 error
    
*   emit 变成 revert
    

文档提到，这种方式可以节省gas，我们来使用 require 编写一个条件校验：

    function withdraw2() public {
        // if (msg.sender != owner)
        //     revert Unauthorized();
        require(msg.sender == owner, "Unauthorized");
    
        owner.transfer(address(this).balance);
    }
    

使用 remix 测试，前者消耗了 23367 的 gas，后者消耗了 23449 的 gas，确实是能够稍微节省一点。

还有一点是这种新的方式可以添加参数，这样就能够直接将运行时的一些数据暴露出来，当出现失败交易的时候能够更准确地排查原因。我们继续来看官方的例子：

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity ^0.8.4;
    
    /// Insufficient balance for transfer. Needed `required` but only
    /// `available` available.
    /// @param available balance available.
    /// @param required requested amount to transfer.
    error InsufficientBalance(uint256 available, uint256 required);
    
    contract TestToken {
        mapping(address => uint) balance;
        function transfer(address to, uint256 amount) public {
            if (amount > balance[msg.sender])
                // Error call using named parameters. Equivalent to
                // revert InsufficientBalance(balance[msg.sender], amount);
                revert InsufficientBalance({
                    available: balance[msg.sender],
                    required: amount
                });
            balance[msg.sender] -= amount;
            balance[to] += amount;
        }
        // ...
    }
    

这里我们发起一笔转账交易，查看 etherscan，只有一个 Fail 提示：

![上传代码之前](https://storage.googleapis.com/papyrus_images/bea94c18d439c8ba3f1f3d92b974175330ca45f1afb78846cd3150cc91bf2e05.png)

上传代码之前

这是因为我们还没有上传代码。上传代码之后：

![上传代码之后](https://storage.googleapis.com/papyrus_images/c6ecc2287f13b69992da4d25b6d5b07b0ee95380238e87bacc96fd1bc2c14e8f.png)

上传代码之后

可以直接从错误信息看到，我们在发起这笔交易的时候，余额只有0，而想要转账的数量是100。

这里要注意的一点是，使用 require 时，不需要上传代码也能够显示出错误提示。

### 参考

[

Custom Errors in Solidity | Solidity Programming Language
---------------------------------------------------------

Posted by Solidity Team on April 21, 2021

https://www.soliditylang.org

![](https://storage.googleapis.com/papyrus_images/be53109a5599b8c5aed1196efc2cb36a41c596ad098008e082306c892d22a5f0.png)

](https://blog.soliditylang.org/2021/04/21/custom-errors/)

---

*Originally published on [xyyme.eth](https://paragraph.com/@xyyme/solidity-error)*
