[ERC7535] ERC4626にネイティブトークンを活用する仕組みを理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、**ERC4626**にETHなどのネイティブトークンを使用する仕組みを提案している規格である**ERC7535**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-7535

:::note warn
**7535**は現在（2024年1月14日）では「**Review**」段階です。
:::

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

この規格は、**ERC4626**という既存の Ethereum コントラクト規格に追加機能をもたらすもので、特に Ether や他のネイティブアセットを基盤資産として取り扱う時のインターフェースと動作をカスタマイズする点に特徴があります。

**ERC4626**は、トークン化された資産を管理するための標準的な方法を定義するEthereumの規格です。
例えば投資ファンドのような金融商品をトークンとして表現するために使用されます。
これにより、トークンホルダーは、そのファンドの資産に対する権利や持ち分を持つことができます。

この拡張を通じて、開発者は**ERC4626**の基本的なフレームワークを利用しつつ、Etherや他のブロックチェーンのネイティブ資産を、コントラクト内で直接的に管理する機能を実装することができます。

この拡張により、Ether やその他のネイティブ資産を使用した新しいタイプの金融商品やサービスを、**ERC4626**の枠組みを活用してより容易に開発することが可能になります。
これにより、Ethereum ブロックチェーン上での資産の取り扱いがより柔軟かつ効率的になることが期待されます。

:::note info
**ERC4626**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/99db4ee3074ab6c8c4e2

# 動機

上記のテキストは、Ether（ETH）をトークン化したヴォルト（**Vaults**）のための新しい標準に関するものです。
この標準は、特に流動性が高いステーキングトークンに焦点を当てており、これらのトークンは**ERC20**ラッパーを介してETHのステーキングを表現します。
言い換えれば、**ERC20**トークンを使用してETHステーキングを可能にします。

この新しい標準は**ERC4626**と同様の利点を持っています。
**ERC4626**は、デジタル資産の管理と流動性を提供するためのEthereumのコントラクト規格です。
新しい標準が**ERC4626**のインターフェースをそのまま維持することで、既存の**ERC4626**ツールやプロトコルとの互換性が最大化され、より多くの利点が得られます。

この標準により、開発者はETHのステーキングに関連する新しいタイプのトークンを効率的に管理するためのフレームワークを利用できます。
これらのトークンは、ETHのステーキングのための**ERC20**ラッパーとして機能し、ユーザーはこれを使用してETHをステーキングできます。

また、**ERC4626**と同じインターフェースを使用することで、新しい標準は既に存在する**ERC4626**対応のツールやプロトコルと簡単に統合できるようになります。
これは、開発者が新しいコードを書く必要が少なくなることを意味し、ユーザーはこれらのトークンをよりスムーズに使用できるようになります。

:::note info
ETHをトークン化したヴォルトのためのこの新しい標準は、**ERC4626**の既存の枠組みを活用して、ETHのステーキングに関連するトークンをより効率的かつ容易に管理できる方法を提供します。
これにより、Ethereum上での資産管理の柔軟性と利便性が高まります。
:::

# 仕様

**ERC7535**に準拠するコントラクトは、以下に指定する**ERC4626**の`asset`、`deposit`、`mint`メソッドをオーバーライドして実装する必要があります。

## ERC-4626 変更点

**ERC7535** 標準では以下のような変更点があります。

- **アセットの量
    - **ERC4626**ではアセットの量は通常**ERC20**トークンのバランスとして扱われますが、**ERC7535**ではアセットの量はEtherのウェイ（`wei`）として扱われます。

- **トランスファーの置き換え**
    - **ERC20**の`transfer`関数の呼び出しが、Etherの送付（`send` または `call`）に置き換えられます。

- 承認フローの除外**
    - **ERC20** での`transferFrom`を使用したアセットの承認フローは、**ERC7535**では実装されていません。

- `deposit`と`mint`の状態変更
    - これらの関数は`payable`としてマークされており、状態変更が可能です。

- `deposit`の使い方
    - `deposit`関数は`msg.value`を主要な入力として使用し、アセットの指定を無視することが許されます。

これらの変更により、**ERC7535** は、Etherを基本資産とするトークン化されたヴォルトにおいて、より効率的かつ柔軟な操作を可能にします。
**ERC4626**と**ERC20**の標準に基づいているため、これらの標準に準拠した既存のツールやプロトコルとの互換性も維持しつつ、Etherの直接取り扱いに特化した機能を提供します。
これにより、Etherを使用する新しい種類のトークン化されたヴォルトを効果的に開発し、運用することが可能になります。

## メソッド

### `asset`

- **関数名**
    - `asset`
- **タイプ**
    - 関数
- **状態**
    - `view`（状態を変更しない読み取り専用の関数）

この `asset` 関数は、入力パラメータを取らず、出力として `assetTokenAddress` という名前のアドレス型の値を返します。
`asset` 関数は、特定のアドレス値「0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE」を必ず返すように設定されています。

このアドレス値は、Ether自体を示すための標準的な方法であり、**ERC7528** で定められています。
通常、トークンのアドレスは特定のコントラクトのアドレスを指しますが、この特別な値はEtherを表すために使用されます。
つまり、`asset` 関数はこのコントラクトがEtherを扱っていることを示すためのもので、実際のトークンのアドレスではなく、Ether自体を表す特殊な値を返します。

:::note info
`asset` 関数はコントラクトが扱う資産がEtherであることを示すために使用され、**ERC7528** に従って特定のアドレス値を返します。
これは、コントラクトがトークンではなく、直接的にEtherを扱っていることを意味します。
:::

### `deposit`

- **関数名**
    - `deposit`
- **タイプ**
    - 関数
- **状態**
    - `payable`（Etherの支払いを受け付ける関数）

`deposit` 関数の主な役割は、Etherを預けることによってヴォルトのシェアを発行することです。
この関数は以下のように動作します。

- **payable**
    - 関数は `payable` であり、Etherの送金を受け付けます。

- **主要な入力パラメータ**
    - この関数は `msg.value`（送信されたEtherの量）を主要な入力パラメータとして使用し、シェアの出力量を計算します。
    - `assets` パラメータは無視される可能性があります。

- **イベントの発生**
    - `Deposit` イベントを発生させる必要があります。

- **取り消しの条件**
    - もし `msg.value` の全額が預けられない場合（例えば、預金限度に達している、スリッページが発生しているなどの理由で）、関数は取り消し（`revert`）する必要があります。

関数の入力と出力は以下の通りです。

- **入力**
    - `assets`
        - `uint256`。
        - Etherの量を表すが、この関数では主に無視される可能性があります。
    - `receiver`
        - `address`。
        - シェアが発行される受取人のアドレス。

- **出力**:
   - `shares`
       - `uint256`。
       - 預けられたEtherに対して発行されるヴォルトのシェアの量。

:::note info
`deposit` 関数はユーザーがEtherを預けることによってヴォルトのシェアを発行するために使われます。
この過程で、預けられたEtherの量（`msg.value`）がシェアの計算の基礎となり、特定の条件下で取り消しを行うことが必要です。
:::

### `mint` 

- **関数名**
    - `mint`
- **タイプ**
    - 関数
- **状態**
    - `payable`（Etherの支払いを受け付ける関数）

`mint` 関数の主な目的は、ETHの資産を預けることによってヴォルトのシェアを正確に発行することです。
この関数の動作は以下の通りです。

- **payable**
    - 関数は `payable` であり、Etherの送金を受け付けます。

- **イベントの発行**
    - `Deposit` イベントを発行する必要があります。

- **revertの条件**
    - もしリクエストされたすべてのシェアが発行できない場合（例えば、預金限度に達している、スリッページが発生している、ユーザーが十分な量の `msg.value` のEtherをヴォルトコントラクトに送っていないなどの理由で）、関数は処理の取り消し（`revert`）する必要があります。

関数の入力と出力は以下の通りです。

- **入力**:
    - `shares`
        - `uint256`。
        - 発行されるヴォルトのシェアの量。
    - `receiver`
        - `address`。
        - シェアが発行される受取人のアドレス。

- **出力**:
   - `assets`
       - `uint256`。
       - 預けられたEtherに対して発行されるヴォルトのシェアに対応する資産の量。

:::note info
`mint` 関数は、ユーザーがEtherを預けることによって指定された量のヴォルトのシェアを発行するために使われます。
この過程で、特定の条件下での取り消しを行うことが必要です。
:::

## イベント

イベントの使用法は**ERC4626**と同じにする必要があります。

## Wrapped ETH

**Wrapped ETH ERC-20**をアセットとして使用する**ERC4626 Vault**は、**ERC7535**を実装できません。
**ERC7535**はネイティブETHにのみ適用されます。

# 補足

ここでの説明は**ERC-4626**との互換性を最大化しつつ、インターフェースにおける詳細を最小限に抑えることを目的としています。

### `deposit` 関数の `assets` 入力の保持
この標準では、`deposit` 関数で `assets` 入力を保持しつつ、その使用をオプショナル（任意）にしています。
`msg.value`（送金されたEtherの量）が預け入れに必要であるため、これを主要な入力数値として扱うことが推奨されます。
`assets` を使用することによる厳密な等価性の強制は余分なガスコストを発生させ、異なる値を許容することは予期せぬ挙動を引き起こす可能性があるためです。

### `mint` 呼び出しにおける `msg.value` と `assets` の不一致
ユーザーが `mint` 関数を呼び出す時に、Etherを多く預けることがあり得ます。
この場合、`msg.value` が `assets` と完全に一致することを強制すると、不必要な取り消しを引き起こすことがあります。
ヴォルトの実装者は、過剰なEtherを返金するか吸収するかを決定する責任があり、預金者は可能な限り正確な額を預けることが推奨されます。

### **ERC4626**からの変更

`fallback`/`__default__` メソッド、追加のヴォルト関数の支払可能性、コントラクトに強制的に送られたETHの取り扱いに関する強制的な行動やその欠如の不許可などの**ERC4626** との実装レベルでのすべての変更は、**ERC20** トークンではなく、Etherまたは他のネイティブ資産の使用に適応するためのものです。

:::note info
この新しい標準は、**ERC4626**との互換性を維持しつつ、Etherやその他のネイティブ資産の効率的かつ柔軟な取り扱いを可能にすることを目的としています。
これにより、開発者やユーザーは既存のツールやプロトコルとの互換性を保ちつつ、Etherの取り扱いをより効率的かつ安全に行うことができるようになります。
:::

## デポジットにおける `assets` パラメーターの無視
デポジットを行う時、`msg.value`（送金されたEtherの量）を指定する必要があります。
このため、`msg.value` を主要な入力数値として扱うことが推奨されています。
`assets` パラメーターを使用することは、厳密な等価性を強制して余分なガス（手数料）コストを発生させる可能性があるため、このパラメーターの使用は省略可能とされています。
また、`assets` が`0`であることを要求することも可能ですが、これは実装レベルでのガスコストが発生するため、`assets` は実質的に無視しても良いとされています。

## ミントにおいて `msg.value` が `assets` 出力と等しくない場合の許容
ユーザーがミントの時にEtherを多く預けるケースが考えられます。
この場合、`msg.value` と `assets` 出力が等しいことを強制すると、不必要な取り消し（`revert`）が生じる可能性があります。
そのため、ヴォルトの実装者は余剰なEtherを返金するか受け取るかを決定する責任があります。
また、預金者はできるだけ正確な金額を預けることが推奨されます。

これらのガイドラインは、Etherの取り扱いをより効率的かつ安全にするためのものです。
ユーザーが予期せぬ手数料を払うリスクを減らし、コントラクトの実装者がシステムを柔軟に運用できるようにするための措置として導入されています。

# 互換性

**ERC7535** は **ERC4626** のインターフェースと基本的な機能をそのまま保持しつつ、Ether（ETH）の取り扱いに関して特別な考慮を加えた設計がなされています。

**ERC7535**では、ETHが**ERC20**に準拠していないという事実を考慮して、いくつかの実装に違いがあります。
例えば、`assets`パラメータよりも`msg.value`送金されたEtherの量）を優先するという点です。
これは、ETHの特性に基づいた適応であり、**ERC4626**の基本的なフレームワークを変えるものではありません。

さらに、**ERC7535**には他の既存の標準との互換性問題がないとされています。
これは、**ERC7535**がEthereumの広範なエコシステム内で問題なく機能し、他の標準ともうまく共存できるように設計されていることを意味します。

**ERC7535**は、**ERC4626** との互換性を維持しつつ、ETHの独自の特性を考慮した拡張を提供することで、Ethereumの様々なアプリケーションやプロトコルにおいて利用の幅を広げることが期待されます。

# セキュリティ

**ERC4626** に関連するセキュリティ上の考慮事項に加えて、ETHをヴォルト資産として使用する時のセキュリティ上の影響について述べています。

## `call` と `send` の使用に関する注意
コントラクトがETHを`transfer`する時、`call` メソッドの使用には注意が必要です。
`call` を使用すると、信頼できる**ERC20**トークンでは発生しない追加のリエントランシー（再入）の脆弱性や任意のコード実行が可能になるリスクがあります。
そのため、少量のガス手当てを伴う `send` を使用してETHを送る方が安全です。
ETHの`transfer`方法を決定する時は、実装者は特に注意を払う必要があります。

## 強制的なETH転送
`SELFDESTRUCT` オペコードを使って、ETHは任意のヴォルトに強制的に送り込むことができます。
このため、ヴォルトの実装者は、このような転送がヴォルトの会計に何らかの形で影響を与えないことを確認する必要があります。
また、追加の支払い可能なメソッドも、ヴォルトの会計に影響を与えないよう慎重にチェックする必要があります。

:::note info
`SELFDESTRUCT` オペコードについては以下の記事を参考にしてください。
:::

https://zenn.dev/heku/books/aef33b86ded3c0/viewer/27cd5d#selfdestruct

:::note info
`SELFDESTRUCT`の動作については以下の記事を参考にしてください。
:::

https://chaldene.net/solidity-selfdestruct

## Wrapped ETHの使用
**ERC4626**を実装するスマートコントラクトシステムは、基本資産として**ERC20**をサポートすることを検討し、ETHの直接的な取り扱いに**ERC7535**を使用する代わりに、Wrapped ETHのような**ERC20**ラッパーを使用することが推奨されています。
これは、**ERC4626**と**ERC7535**の間の微妙な違いがコードの断片化やセキュリティ上の懸念を引き起こす可能性があるためです。
Wrapped ETHやLiquid Staking Tokensのような、ETH専用のケースは**ERC7535**にとってより適切な使用例です。

これらのポイントは、ETHをヴォルト資産として取り扱う時の特有のセキュリティリスクを強調し、それらを軽減するための推奨されるアプローチを提供しています。
安全性を確保するために、実装者はこれらの懸念事項を慎重に考慮し、適切な対策を講じる必要があります。

# 引用

Joey Santoro (@joeysantoro), "ERC-7535: Native Asset ERC-4626 Tokenized Vault [DRAFT]," Ethereum Improvement Proposals, no. 7535, October 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7535

# 最後に

今回は「**ERC4626**にETHなどのネイティブトークンを使用する仕組みを提案している規格である**ERC7535**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4