# Solidity 0.8.26での変更点まとめ

> Solidityのバージョン0.8.26では以下の項目が変更されました。

- URL: https://cardene.dev/articles/fc4392ce6c27ef
- 公開日: 2024-05-25
- 更新日: 2024-05-25
- トピック: Blockchain
- タグ: ブロックチェーン, solidity, ethereum, smartcontract

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください！

https://twitter.com/cardene777

https://chaldene.net/

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

今回はSolidityのバージョン0.8.26が2024年5月21日にリリースされたので、その変更点をまとめていきます。

以下の公式のリリース記事をもとにまとめていきます。

https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

# 変更点

Solidityのバージョン0.8.26では以下の項目が変更されました。

- `require`でのcustomエラーサポート
- エンコードサイズが小さいカスタムエラーの最適化
- 高速なYul Optimizerシーケンス
- コンパイル時に使用されるJSONライブラリの変更

# `require`でのcustomエラーサポート

カスタムエラーとは、以下のように任意のエラーを自分で定義できる機能です。

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

contract Solidity0826 {
    uint256 requiredAmount = 0.01 ether;

    error InsufficientBalance(uint256 available, uint256 required);

    function deposit() public payable {
        if (msg.value <= 0.001 ether) {
            revert InsufficientBalance(msg.value, requiredAmount);
        }
    }
}
```

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

```solidity
error InsufficientBalance(uint256 available, uint256 required);
```

上記で`InsufficientBalance`というエラーを定義しておきます。

```solidity
if (msg.value <= 0.001 ether) {
    revert InsufficientBalance(msg.value, requiredAmount);
}
```

その後、上記のようにif文などの条件にマッチした場合に、先ほど定義したエラーを返すようにします。

エラーを返すときによく使用されるエラーとしては、`require`というものがあります。
こちらの方がより一般的かつ、ガス効率が良いです。

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

contract Solidity0826 {
    uint256 requiredAmount = 0.01 ether;

    error InsufficientBalance(uint256 available, uint256 required);

    function deposit() public payable {
        require(msg.value > 0.001 ether, "InsufficientBalance");
    }
}
```

上記のrequireでは、`msg.value > 0.001 ether`という条件に一致しない場合は、`InsufficientBalance`というメッセージを返して処理を止めます。
しかし、Solidiry 0.8.25以前までは`require`のメッセージ部分にカスタムエラーを入れることができませんでした。

Solidiry 0.8.26では、ここにカスタムエラーを入れられるようになりました。

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

contract Solidity0826 {
    uint256 requiredAmount = 0.01 ether;

    error InsufficientBalance(uint256 available, uint256 required);

    function deposit() public payable {
        require(
            msg.value > 0.001 ether ,
            InsufficientBalance(msg.value, requiredAmount)
        );
    }
}
```

これにより以前のカスタムエラーよりもガス効率が良くなります。

ただ、一点注意が必要です。
それは、コンパイル時にIRパイプライン（Yul経由でのコンパイル）でのみこの機能がサポートされているということです。
IRパイプラインとは、直接コードをバイトコードに変換するのではなく、中間表現（人間が読みやすいコードと機械語の中間に位置する表現形式）に変換して、より効率的なバイトコードを生成するコンパイル方式です。
SolidityではYulという中間表現があります。

:::message
Yulについては、以下の記事にを参考にしてください。
:::

https://zenn.dev/heku/books/c28469224e315f/viewer/0799d1

hardhatとremixでのIRパイプラインでのコンパイルをする方法を簡単に説明しておきます。

### hardhat

`hardhat.config.js`で以下のように`viaIR: true,`を追加してください。

```diff js:hardhat.config.js
solidity: {
  version: "0.8.24", // any version you want
  settings: {
+   viaIR: true,
    optimizer: {
      enabled: true,
      details: {
        yulDetails: {
          optimizerSteps: "u",
        },
      },
    },
  },
}
```

https://hardhat.org/hardhat-runner/docs/reference/solidity-support

### remix

remixでは、`compiler_config.json`に以下のように、`"viaIR": true,`を追加してください。

```diff json:compiler_config.json

{
	"language": "Solidity",
	"settings": {
+		"viaIR": true,
		"optimizer": {
			"enabled": true,
			"runs": 200
		},
		"outputSelection": {
			"*": {
			"": ["ast"],
			"*": ["abi", "metadata", "devdoc", "userdoc", "storageLayout", "evm.legacyAssembly", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "evm.gasEstimates", "evm.assembly"]
			}
		}
	}
}
```

### ソースコード

remixで作成したソースコードも載せておきます。

https://gist.github.com/cardene777/fbb3435fe20ea94aed1be9b016824d12

# エンコードサイズが小さいカスタムエラーの最適化

これまでカスタムエラーを使用して処理を`revert`（中断）する時のコードの最適化には、インラインアセンブリを使用していました。

https://ethereum.stackexchange.com/questions/142752/yul-inline-assembly-revert-with-a-custom-error-message

https://stackoverflow.com/questions/73373480/solidity-yul-inline-assembly-revert-with-custom-error

https://stackoverflow.com/questions/73373480/solidity-yul-inline-assembly-revert-with-custom-error/74704254

:::message
インラインアセンプリについては、以下の記事にを参考にしてください。
:::

https://zenn.dev/heku/books/c28469224e315f/viewer/bce7f7

Solidiry 0.8.26では、引数のないカスタムエラーやメモリ領域に収まる程度のサイズのカスタムエラーの場合、デプロイ段階でガスコストを自動で最適化してくれるようになります。
これにより、インラインアセンプリでカスタムエラーコードを最適化する必要がなくなります。

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;

error ForceFailure();

contract FailureForcer {
    function fail() external pure {
        revert ForceFailure();
    }
}
```

引数のないカスタムエラーは上記のようなエラーです。

# 高速なYul Optimizerシーケンス

Yul Optimizerを使用してコンパイルするときのシーケンス（どのように最適化するか）に、新しいデフォルトシーケンスを導入することが決まりました。
新しいデフォルトシーケンスでは、コードの最適化の精度を維持しつつ、コンパイル時間を大幅に短縮しています。

これまでは最適化の手順を複数回繰り返して最適化の機会を増やしていましたが、解析の結果、最初の最適化と最終結果がほとんど変わらないことがわかりました。

![高速なYul Optimizerシーケンスの図](https://storage.googleapis.com/zenn-user-upload/c622f66950b2-20240525.png)
引用: https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

そのため、新しいデフォルトシーケンスでは繰り返しの回数を減らして、1回の最適化が行われるように変更されました。

![高速なYul Optimizerシーケンスの図](https://storage.googleapis.com/zenn-user-upload/0f0dbba8311b-20240525.png)
引用: https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

ガス代の効率化も同じように1回の最適化に変換したようです。

これまでのシーケンス
![高速なYul Optimizerシーケンスの図](https://storage.googleapis.com/zenn-user-upload/c2d1e1e55878-20240525.png)
引用: https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

新しいシーケンス
![高速なYul Optimizerシーケンスの図](https://storage.googleapis.com/zenn-user-upload/0eb7909b29fc-20240525.png)
引用: https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

これにより、以下の図のように多くのプロジェクトでコンパイル時間が最大65%まで減少しました。

| プロジェクト          | コンパイル時間の減少率 | バイトコードサイズの変化 | 実行時ガスコストの変化 |
|---------------------|------------------|----------------------|--------------------|
| pool-together       | -63%             | -1.29%               | 未測定             |
| uniswap             | -53%             | +1.67%               | 未測定             |
| zeppelin            | -47%             | -0.48%               | -0.01%             |
| elementfi           | -42%             | -1.87%               | 未測定             |
| euler               | -34%             | +1.00%               | 未測定             |
| yield_liquidator    | -27%             | +0.84%               | +0.14%             |
| ens                 | -22%             | -1.20%               | -0.01%             |
| brink               | -20%             | +0.61%               | 未測定             |
| perpetual-pools     | -16%             | -0.23%               | +0.02%             |
| gp2                 | -12%             | +0.50%               | 未測定             |

注意点として、0.8.21以前のバージョンで問題となった脆弱性があり、新しいデフォルトシーケンスは0.8.22以降で使うようにして、それ以前のバージョンでは古いシーケンスを使用する必要があります。

# コンパイル時に使用されるJSONライブラリの変更

コンパイル内部で使用されているJSONライブラリを、`jsoncpp`というライブラリから`nlohmann::json`というライブラリに変更されました。

https://github.com/open-source-parsers/jsoncpp
https://github.com/nlohmann/json

これによりUTF-8エンコーディング（可変長の文字エンコーディング方式）がより厳密になり、不正なUTF-8シーケンスが許容されなくなります。

また、速度も上がる？ようです。

https://github.com/nlohmann/json/issues/1633

# その他の変更

その他の細かい修正については以下の記事を参考にしてください。

https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

# 参考

https://soliditylang.org/blog/2024/05/21/solidity-0.8.26-release-announcement

https://web3blog.playmining.com/solidity-0.8.26

# 最後に

今回はSolidityのバージョン0.8.26の変更点をまとめました。

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください！

https://twitter.com/cardene777

https://chaldene.net/

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9
