[ERC7254] ERC20トークン保有者への新しい収益分配方法の仕組みを理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、**ERC20**トークンの保有者への報酬の自動更新や引き出し機能など、追加の手間なしに報酬を得る仕組みを提案している**ERC7254**についてまとめていきます！

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

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

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

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

# 概要

このプロジェクトは、**ERC20**トークンの所有者にユニークな機能を提供し、トークンの価値を高めることを目指しています。
具体的には、トークン保有者に対して、トークンをロックしたり、ステーキングしたり、ファーミングすることなく、簡単に報酬を提供する方法です。
プロジェクトが利益を生み出すたびに、その利益はトークン保有者に分配されます。

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

https://chaldene.net/erc20

この概念を「**Revenue Sharing**」と呼び、これは**ERC20**トークンの拡張版と見なすことができます。
**Revenue Sharing**は、トークン保有者に対して追加の支払い方法を提案し、保有者の報酬を更新し、報酬を引き出すことを可能にします。

潜在的な利用例としては、次のようなものが考えられます。

- 企業がトークン保有者に配当を分配する。
- マーケットプレイス、自動市場作成機関（AMM）、ゲームなどのビジネス活動から得られた収益を直接共有する。

:::note info
このシステムはトークン保有者がプロジェクトの成功から直接利益を得られるようにするものであり、トークン保有者は追加のアクションを取らずとも、自動的に報酬を受け取ることができます。
これにより、トークン保有者とプロジェクト運営者の間でより強い絆が築かれ、プロジェクトへの長期的なコミットメントを促進することが期待されます。
:::

# 仕様

## メソッド

### `maxTokenReward`

```javascript
function maxTokenReward() public view returns (uint256)
```

**概要**

最大トークン報酬を返す関数。

**詳細**

この関数は、コントラクトが保有者に提供できる最大のトークン報酬の量を返します。
これは、コントラクトの設定や現在の利益分配ルールに基づいています。


**戻り値**

- `uint256`
    - コントラクトが提供できる最大のトークン報酬量。

---

### `informationOf`

```javascript
function informationOf(address token, address account) public view returns (UserInformation memory)
```

**概要**

特定のアカウントの情報を返す関数。

**詳細**

この関数は、指定されたトークンとアカウントアドレスに関連するアカウント情報を返します。
情報には、報酬に関連する`inReward`、`outReward`、そして引き出された総報酬量`withdraw`が含まれます。

**引数**

- `address token`
    - 情報を取得したいトークンのアドレス。
- `address account`
    - 情報を取得したいアカウントのアドレス。

**戻り値**

- `UserInformation memory`
    - 指定されたアカウントの情報を含む`UserInformation`構造体。

---

### `informationOfBatch`

```javascript
function informationOfBatch(address account) public view returns (UserInformation[] memory)
```

**概要**

複数のアカウント情報をリストで返す関数。

**詳細**

この関数は、指定されたアカウントに関連する複数のアカウント情報を一括で返します。
各アカウント情報には、`inReward`、`outReward`、そして引き出された総報酬量`withdraw`が含まれます。

**引数**

- `address account`
    - 情報を取得したいアカウントのアドレス。

**戻り値**

- `UserInformation[] memory`
    - 指定されたアカウントに関連する情報を含む`UserInformation`構造体の配列。

---

### `tokenReward`

```javascript
function tokenReward() public view returns (address[] memory)
```

**概要**

トークン報酬のアドレスリストを返す関数。

**詳細**

この関数は、報酬として設定されているトークンのアドレスリストを返します。
これにより、どのトークンが報酬システムに組み込まれているかを確認することができます。


**戻り値**

- `address[] memory`
    - 報酬として設定されているトークンのアドレスリスト。

---

### `updateReward`

```javascript
function updateReward(address[] memory token, uint256[] memory amount) public
```

**概要**

トークン報酬の`rewardPerShare`を更新する関数。

**詳細**

この関数は、指定されたトークンの報酬割合（`rewardPerShare`）を更新します。
新しい報酬割合は、現在の割合に加えて、指定された量をトークンの総供給量で割ったものによって計算されます。

**引数**

- `address[] memory token`
    - 更新するトークンのアドレスの配列。
- `uint256[] memory amount`
    - 各トークンに追加する報酬量の配列。

---

### `viewReward`

```javascript
function viewReward(address account) public view returns (uint256[] memory)
```

**概要**

アカウントに対する報酬量のリストを返す関数。

**詳細**

この関数は、指定されたアカウントに対して利用可能な報酬のリストを返します。
各トークンに対する報酬量がリスト形式で返されます。

**引数**

- `address account`
    - 報酬量を確認したいアカウントのアドレス。

**戻り値**

- `uint256[] memory`
    - 指定されたアカウントに対する各トークンの報酬量のリスト。

---

### `getReward`

```javascript
function getReward(address[] memory token) public
```

**概要**

リストされたトークン報酬を取得する関数。

**詳細**

この関数は、指定されたトークンの報酬を取得し、それらの報酬を呼び出し元のアカウントに送信します。
トークン報酬は、そのアカウントが受け取るべきものです。

**引数**

- `address[] memory token`
    - 報酬を取得したいトークンのアドレスの配列。

---

### `getRewardPerShare`

```javascript
function getRewardPerShare(address token) public view returns (uint256)
```

**概要**

トークン報酬の1株当たりの報酬を返す関数。

**詳細**

この関数は、指定されたトークンについて、1株当たりの報酬量（`rewardPerShare`）を返します。
これにより、トークン保有者は自分の保有量に基づく報酬の見積もりを計算できます。

**引数**

- `address token`
    - 報酬の1株当たりの量を知りたいトークンのアドレス。

**戻り値**

- `uint256`
    - 指定されたトークンの1株当たりの報酬量。

---

### `existsTokenReward`

```javascript
function existsTokenReward(address token) public view returns (bool)
```

**概要**

トークン報酬のステータスを返す関数。

**詳細**

この関数は、指定されたトークンが報酬システムに存在するかどうかのステータスを返します。
これにより、特定のトークンが報酬として利用可能かどうかを確認できます。

**引数**

- `address token`
    - ステータスを確認したいトークンのアドレス。

**戻り値**

- `bool`
    - 指定されたトークンが報酬システムに存在する場合は`true`、そうでない場合は`false`。

---

### `UserInformation`

```javascript
struct UserInformation {
    uint256 inReward;
    uint256 outReward;
    uint256 withdraw;
}
```

**概要**

ユーザーの報酬情報を保持する構造体。

**詳細**

この構造体は、ユーザーの報酬に関連する3つの主要な情報を格納します。
`inReward`はユーザーのバランスが減少した時に更新され、`outReward`はユーザーのバランスが増加した時に更新されます。
`withdraw`はユーザーによって引き出された報酬トークンの総量を示します。
これにより、ユーザーの報酬履歴と現状を追跡しやすくなります。

**パラメータ**

- `inReward`
    - ユーザーのバランスが減少した際に更新される報酬の量。
- `outReward`
    - ユーザーのバランスが増加した際に更新される報酬の量。
- `withdraw`
    - ユーザーによって引き出された報酬トークンの総量。

---

# 実装

- [ERC7254](https://eips.ethereum.org/assets/eip-7254/ERC7254.sol)
- [IERC7254](https://eips.ethereum.org/assets/eip-7254/IERC7254.sol)

# 引用

Quy Phan (@quyphandang), Quy Phan <quy.phan@cryptoviet.info>, "ERC-7254: Token Revenue Sharing [DRAFT]," Ethereum Improvement Proposals, no. 7254, June 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7254.

# 最後に

今回は「**ERC20**トークンの保有者への報酬の自動更新や引き出し機能など、追加の手間なしに報酬を得る仕組みを提案している**ERC7254**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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