# [ERC5115] 利回り資産の共通規格を定めるSYトークンの仕組みを理解しよう！

> ERC5115では、スマートコントラクト内で利用できる「利回り付きトークン（yield-bearing token）」をラップ（包み込む）ためのAPIを提案しています。

- URL: https://cardene.dev/articles/777a83016a6f439e7941
- 公開日: 2025-10-30
- 更新日: 2025-10-30
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、DeFi（分散型金融）で利回りを生むトークンを共通の方法で扱えるようにするための新しいトークン標準「**Standardized Yield（SY）**」を定めている**ERC5115**についてまとめていきます！

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

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

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

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

## 概要

**ERC5115**では、スマートコントラクト内で利用できる「**利回り付きトークン（yield-bearing token）**」をラップ（包み込む）ためのAPIを提案しています。
このAPIは **ERC20**トークン（基本的なトークン送付・残高管理機能を持つ標準規格）を拡張したものであり、以下の操作をサポートします。

* トークンの送信（transfer）
* 預入（deposit）
* 引き出し（withdraw）
* 残高照会（balance reading）

つまり、単なるトークン送付にとどまらず、利回りを生むトークンを安全かつ統一的に扱うためのインターフェースを提供するものです。

## 動機

利回りを生み出す仕組みは、プロトコルごとに多様であり、それぞれ独自の実装をしています。
そのため、あるプロトコルが別のプロトコル上に構築された利回り機構を利用する時には、その都度「**手動での統合作業**」が必要となっていました。

これを解消するために登場したのが**ERC4626**です。
**ERC4626**は「**Vault（資産保管庫）**」と呼ばれるカテゴリの利回り生成メカニズムに共通のインターフェースを定義し、開発者が効率的に統合できるようにしました。

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

[\[ERC4626\] あるトークンを保有していると報酬を受け取れる標準規格の仕組みを理解しよう！](/articles/99db4ee3074ab6c8c4e2)

しかし、**ERC4626**では対応しきれないケースもあります。
**ERC5115**は、そのギャップを埋め、より多様な資産や仕組みに対応することを目的としています。

#### ERC4626では対応できない資産の例

##### 入金トークンと価値算定トークンが異なる資産

一部の利回り資産は、「**発行（mint）**」時に使用するトークンと、「**プール全体の価値**」を表すトークンが異なります。
例えば **AMM（自動マーケットメイカー）**の流動性トークンは、スワップ手数料を通じて利回りを生みますが、その価値は「**流動性単位（liquidity units）**」で表されます。
この単位は実際のトークンではないため、**ERC4626**のように直接「**預入**」できません。
（例：Uniswap V2の流動性トークンは、ホワイトペーパーに定義される独自の仕組みで価値を計算します）

**ERC5115**では、そのようなケースにも柔軟に対応できるようになります。
例えば、ETHを扱うVaultが「**ガス代削減**」や「**使いやすさ**」を目的として、ETHの代わりに **cETH**（CompoundでETHを預けると発行されるトークン）を直接受け入れることも可能になります。

##### 報酬トークンを伴う資産

Compoundのようなプロトコルでは、資産を預けると利息だけでなく報酬トークン（例：COMP）が付与されます。
**ERC5115**では、こうした報酬トークンの処理（報酬を売却して元資産に組み込むなど）を標準的に扱えるように設計されています。
さらに拡張すれば、複数の報酬トークンを同時に扱うことも可能です。

#### なぜ新しい標準が必要なのか

**ERC4626**は多くのVaultに適しており、今後も主流の標準であり続けると考えられます。
しかし、以下のような場合には、より柔軟な仕組みが求められます。

* LPトークン（流動性提供トークン）など、Vaultではない形態の利回り資産
* 異なる入金・評価方法を持つプロトコル
* 報酬トークンの複雑な取り扱いを必要とするケース

これらを包括的に扱うために、新たに**Standardized Yield（SY）**という仕組みが提案されています。

#### Standardized Yield（SY）の目的と位置づけ

SYは、DeFi（分散型金融）におけるあらゆる利回り生成メカニズムを統一的に扱うための柔軟な標準です。

SYトークンの特徴は以下のとおりです。

| 機能            | 説明                               |
| ------------- | -------------------------------- |
| **ERC20**の拡張     | 転送・残高確認などの基本操作を保持しつつ、預入・引き出しも標準化 |
| **ERC4626**との互換性 | **ERC4626** Vaultの上位層として動作可能        |
| 柔軟な統合性        | 任意の利回り資産をラップして扱える                |
| 拡張性           | 報酬トークンの処理を追加できる                  |

#### 今後の見通し

**ERC4626**は引き続きVaultの標準として利用される見込みです。
* **SYトークン**は**ERC4626**を含む多様な利回り資産を統一的に扱えるため、DeFi全体の相互運用性を高めます。
* 開発者は、既存のSYトークンを利用するか、新しいSYトークンを実装して目的の資産をラップできます。
* 将来的には報酬トークンの処理や複数報酬の対応なども標準化される可能性があります。

## 仕様

#### 一般的な利回り生成プール

まず、「**GYGP（Generic Yield Generating Pool）**」というモデルを紹介します。これは、DeFi（分散型金融）における多くの利回り生成メカニズムを説明するための共通モデルです。

すべての利回り生成メカニズムには「**資金プール**」が存在します。
このプールは複数のユーザーから流動性を受け取り、その見返りとして「**シェア（shares）**」を発行します。
シェアはプールの所有権を表し、時間の経過とともにプールの価値が上昇するため、各シェアの価値も増加していきます。
また、プールは一定の報酬トークン（reward tokens）を得て、それをユーザーに分配します。

#### GYGPの用語定義

| 用語 | 説明        |
| --------------------- | ------- |
| asset（アセット）           | プールの価値を測定する単位。時刻 $t$ におけるプール全体の価値は`TotalAsset(t)`。 |
| shares（シェア）  | プールの所有権を表す単位。時刻 $t$ におけるシェア総量は`TotalShares(t)`。    |
| reward tokens（報酬トークン） | プールが時間の経過とともに獲得する追加の報酬トークン。                    |
| exchange rate（交換レート）  | 時刻 $t$ において、1シェアが何アセットに相当するかを示す比率。                 |
| users（ユーザー）           | 各ユーザー`u`が保有するシェア数、およびそれに対応する資産価値と報酬トークンの合計。    |

#### 状態変化の例

1. ユーザーが資産を預け入れる（deposit）と、新しいシェアが発行されユーザーに割り当てられます。
2. プールが利回りを得ると、全体の資産量が増加して結果的に交換レートが上昇します。
3. プールが報酬トークンを得ると、各ユーザーに報酬が分配されます。

#### DeFiにおけるGYGPの例

| 利回り生成メカニズム  | アセット  | シェア | 報酬トークン | 交換レート    |
| ------ | ----------- | -------- | ------ | ----- |
| CompoundでUSDCを預ける  | `USDC` | `cUSDC` | `COMP`   | `USDC` 価値/ `1cUSDC`（利息で増加）       |
| LidoでETHをステーキング                | `stETH`       | `wstETH`   | なし     | `stETH` 価値/ `1wstETH`（報酬で増加）     |
| LooksRareでLOOKSをステーク           | `LOOKS`       | `shares`   | `WETH`   | `LOOKS` 価値/ `1share`（報酬で増加）      |
| SushiSwapでETH+USDC流動性を提供       | `ETH` + `USDC` 流動性 | `SLP` トークン  | なし     | `ETHUSDC` 価値/ `1SLP`（スワップ手数料で増加） |
| Curveの3crvプールにUSDC+USDT+DAIを提供 | 3crv流動性     | 3crvトークン | `CRV`    | 流動性価値/1トークン（スワップ手数料で増加）    |

### 標準化された利回りトークン規格

#### 概要

Standardized Yield（略称：SY）は、GYGPモデルに基づいたすべての利回り生成メカニズムに対応するトークン標準です。
各SYトークンはGYGP内のシェアを表し、統一的なインターフェースを通じてGYGPと相互作用できます。

#### SYトークンの要件

| 要件  | 内容  |
| -------- | ---------------------- |
| **ERC20の実装** | SYトークンは必ず**ERC20**を実装し、シェアの表現に利用します。                                      |
| **メタデータの実装** | `name`, `symbol`, `decimals` を持ち、基礎となるGYGP資産の情報を反映します。                |
| **ERC2612の任意実装** | トークン承認のUXを改善するために任意で実装可能です。|
| **Transfer制限**  | 一部のSYトークンは非転送可能とする場合があり、その場合は`transfer`や`transferFrom`呼び出しでrevertします。 |

#### SYに追加される定義

| 用語                    | 説明                                    |
| --------------------- | ------------------------------------- |
| input tokens（入力トークン）  | プールに入る際に資産へ変換可能なトークン。1つのSYで複数対応可能。    |
| output tokens（出力トークン） | プールから出る際にアセットを変換できるトークン。1つのSYで複数対応可能。 |

### インターフェース仕様

#### `IStandardizedYield`

```javascript
interface IStandardizedYield {
    event Deposit(
        address indexed caller,
        address indexed receiver,
        address indexed tokenIn,
        uint256 amountDeposited,
        uint256 amountSyOut
    );

    event Redeem(
        address indexed caller,
        address indexed receiver,
        address indexed tokenOut,
        uint256 amountSyToRedeem,
        uint256 amountTokenOut
    );

    function deposit(
        address receiver,
        address tokenIn,
        uint256 amountTokenToDeposit,
        uint256 minSharesOut,
        bool depositFromInternalBalance
    ) external returns (uint256 amountSharesOut);

    function redeem(
        address receiver,
        uint256 amountSharesToRedeem,
        address tokenOut,
        uint256 minTokenOut,
        bool burnFromInternalBalance
    ) external returns (uint256 amountTokenOut);

    function exchangeRate() external view returns (uint256 res);

    function getTokensIn() external view returns (address[] memory res);

    function getTokensOut() external view returns (address[] memory res);

    function yieldToken() external view returns (address);

    function previewDeposit(address tokenIn, uint256 amountTokenToDeposit)
        external
        view
        returns (uint256 amountSharesOut);

    function previewRedeem(address tokenOut, uint256 amountSharesToRedeem)
        external
        view
        returns (uint256 amountTokenOut);

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}
```

#### 関数仕様

##### `deposit`

```javascript
function deposit(
    address receiver,
    address tokenIn,
    uint256 amountTokenToDeposit,
    uint256 minSharesOut,
    bool depositFromInternalBalance
) external returns (uint256 amountSharesOut);
```

資産を預け入れてSYトークンを発行する関数。
`amountTokenToDeposit`分の`tokenIn`を預け入れ、対応するSYシェアを受け取ります。
内部残高（`depositFromInternalBalance = true`）を使う場合は直接引き落とされ、そうでない場合は通常の`approve`/`transferFrom`フローで入金されます。
失敗条件（承認不足やスリッページなど）に該当する場合は `revert` します。

**引数**

* `receiver`
  　受取アドレス。
* `tokenIn`
  　預け入れる入力トークンのアドレス。
* `amountTokenToDeposit`
  　預け入れるトークン量。
* `minSharesOut`
  　期待される最小SYシェア量。
* `depositFromInternalBalance`
  　内部残高からの入金を行うかどうかのフラグ。

**戻り値**

* `amountSharesOut`
  　発行されたSYシェアの量。

##### `redeem`

```javascript
function redeem(
    address receiver,
    uint256 amountSharesToRedeem,
    address tokenOut,
    uint256 minTokenOut,
    bool burnFromInternalBalance
) external returns (uint256 amountTokenOut);
```

SYシェアを償還して、基礎資産または出力トークンを受け取る関数。
指定したシェアをBurnして、`tokenOut`に変換された資産を受け取ります。
内部残高を使う場合（`burnFromInternalBalance = true`）は直接Burnされます。
不正条件（承認不足・スリッページ超過など）では `revert` します。

**引数**

* `receiver`
  　出力トークンを受け取るアドレス。
* `amountSharesToRedeem`
  　償還するSYシェア量。
* `tokenOut`
  　出力されるトークンのアドレス。
* `minTokenOut`
  　期待される最小出力量。
* `burnFromInternalBalance`
  　内部残高から直接バーンするかどうかのフラグ。

**戻り値**

* `amountTokenOut`
  　実際に受け取る出力量。

##### `exchangeRate`

```javascript
function exchangeRate() external view returns (uint256 res);
```

SYシェアとアセット間の最新交換レートを返す関数。
SYトークン量を資産量に変換するための比率を返します。
`1e18` のスケーリング係数で表現されます。
内部手数料などは含まれません。

**戻り値**

* `res`
  　現在の交換レート。

##### `getTokensIn`

```javascript
function getTokensIn() external view returns (address[] memory res);
```

SYコントラクトが受け入れる入力トークン一覧を返す関数。
利用可能なすべての入金トークンアドレスを返します。
少なくとも1つは必ず含まれ、エラーにはなりません。

**戻り値**

* `res`
  　入力可能なトークンアドレス一覧。

##### `getTokensOut`

```javascript
function getTokensOut() external view returns (address[] memory res);
```

SYコントラクトが出力可能なトークン一覧を返す関数。
出金時に変換できるすべてのトークンアドレスを返します。
少なくとも1つは必ず含まれます。

**戻り値**

* `res`
  　出力トークンアドレス一覧。

##### `yieldToken`

```javascript
function yieldToken() external view returns (address);
```

SYトークンがラップしている元の利回りトークンのアドレスを返す関数。
GYGPに対応する基礎トークン（**ERC20**互換）のアドレスを返します。
ラップされていないSYの場合はゼロアドレスを返すことがあります。

**戻り値**

* `address`
  　基礎となる利回りトークンのアドレス。

##### `previewDeposit`

```javascript
function previewDeposit(address tokenIn, uint256 amountTokenToDeposit)
    external
    view
    returns (uint256 amountSharesOut);
```

入金時に想定されるSYシェアの発行量を見積もる関数。
指定された条件で`deposit`を実行した場合に得られるシェア数をシミュレーションします。
実際の値より大きな結果を返してはなりません。

**引数**

* `tokenIn`
  　入金に使用するトークンのアドレス。
* `amountTokenToDeposit`
  　入金予定のトークン量。

**戻り値**

* `amountSharesOut`
  　想定されるSYシェア量。

##### `previewRedeem`

```javascript
function previewRedeem(address tokenOut, uint256 amountSharesToRedeem)
    external
    view
    returns (uint256 amountTokenOut);
```

償還時に得られるトークン量を見積もる関数。
指定されたシェア量を償還した場合の出力量をシミュレーションします。
実際の結果より大きい値を返してはなりません。

**引数**

* `tokenOut`
  　出力トークンのアドレス。
* `amountSharesToRedeem`
  　償還するSYシェア量。

**戻り値**

* `amountTokenOut`
  　想定される出力量。

#### イベント

##### `Deposit`

```javascript
event Deposit(
    address indexed caller,
    address indexed receiver,
    address indexed tokenIn,
    uint256 amountDeposited,
    uint256 amountSyOut
);
```

トークンがSYに変換され、SYが受取人に送られたときに発行されるイベント。
`deposit`関数を通じて入金が行われた時に必ず発行されます。

**パラメータ**

* `caller`
  　関数を呼び出したアドレス。
* `receiver`
  　SYシェアを受け取ったアドレス。
* `tokenIn`
  　預け入れられたトークンのアドレス。
* `amountDeposited`
  　入金されたトークン量。
* `amountSyOut`
  　発行されたSYトークン（シェア）量。

##### `Redeem`

```javascript
event Redeem(
    address indexed caller,
    address indexed receiver,
    address indexed tokenOut,
    uint256 amountSyToRedeem,
    uint256 amountTokenOut
);
```

SYトークンが償還され、対応する出力トークンが受取人に送られたときに発行されるイベント。
`redeem`関数を通じてSYトークンを出力トークンに変換した時に必ず発行されます。

**パラメータ**

* `caller`
  　関数を呼び出したアドレス。
* `receiver`
  　出力トークンを受け取ったアドレス。
* `tokenOut`
  　出力トークンのアドレス。
* `amountSyToRedeem`
  　償還されたSYトークン量。
* `amountTokenOut`
  　受け取った出力トークン量。

#### 「SY」という名称について

「**SY（読み方：サイ）**」は “Standardized Yield” の略です。
この名称は、標準化された再利用可能な利回り資産の概念を的確に表現するために選ばれました。
SYは単なる略称ではなく、DeFiにおける利回り資産の共通的インターフェースとしての役割を示しています。

## 補足

**ERC5115**では、SYトークンに**ERC20**を必須採用します。
理由は、送付（`transfer`）、承認（`approve`/`transferFrom`）、残高計算（`balanceOf`）といった基本動作がそのままSYトークンにも適用でき、既存の**ERC20**対応エコシステム（ウォレットやアグリゲータ、他のコントラクト）と即時に互換性を持てるためです。
実装者や統合先が新たな学習やアダプタを必要とせず、導入コストを最小化できます。

インターフェース検出のために**ERC165**を任意で実装できます。
これにより、統合先は `IStandardizedYield` の実装有無をプログラム的に判定しやすくなります。

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

[\[ERC165\] コントラクトが特定のインターフェースをサポートしているか確認する仕組みを理解しよう！](/articles/541184977a5cba51b759)

承認UXの改善のために**ERC2612**（Permit）を任意で実装できます。署名ベースの承認フローを使えるようになり、ユーザーの操作手数を減らせます。

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

[\[ERC2612\] ERC20のapproveとtransferFromを1つのトランザクションで実行できる仕組みを理解しよう！](/articles/6809173b2ac428b1ccd0)

| 規格  | 採用区分 | 目的                |
| ----------- | ---- | ------------------- |
| **ERC20**   | 必須   | 基本動作（送付・承認・残高計算）をSYに継承し、既存のユースケースと即時互換にする。 |
| **ERC165**  | 任意   | `IStandardizedYield` 実装の検出を容易にする。          |
| **ERC2612** | 任意   | 承認時のUXを改善し、統合時の操作負担を軽減する。                  |

## 互換性

**ERC5115**は**ERC20**の機能拡張として実装されるため互換性を保持します。
既存の**ERC20**を前提とする仕組みは、SYトークンをそのまま扱えます。

一方で、メタデータ拡張（`name`、`symbol`、`decimals`）の語義はすべてのSY実装で必ず実装する必要があります。
これらは基礎となるGYGPの会計上のアセット情報を正しく反映し、名称や単位の解釈に揺らぎが生じないようにします。

## セキュリティ

**ERC5115**のインターフェースに準拠していても、実装が悪意を持つ場合はユーザーにリスクを与えます。
ウォレット、アグリゲータ、その他のスマートコントラクトなど、統合側は実装内容をレビューし、資金喪失や不正挙動につながる可能性を避けるべきです。

特に `yieldToken` の返すアドレスは、ラップ対象の利回りトークンを厳密に反映する必要があります。
SYがネイティブ実装で、特定の利回りトークンをラップしておらずGYGPのシェアをネイティブに表す場合のみ、ゼロアドレスを返してもかまいません。
そうでないのに不正確なアドレスを返すと、SYの意味や参照先が誤解され、悪意ある実装とみなされるおそれがあります。

| 論点   | 説明      |
| ----------------- | ------------ |
| 準拠＝安全ではない    | 準拠だけで安全は担保されません。統合側での実装レビューが推奨されます。                |
| `yieldToken` の厳密性 | ラップしている場合は正確な基礎トークンのアドレスを返すこと。ネイティブ実装の場合のみゼロアドレス可。 |
| 誤解の回避  | 誤った `yieldToken` はSYの意味を曖昧にし、悪意ある挙動と解釈される可能性があります。 |

以上により、SYは既存の**ERC20**互換性を維持しつつ、検出性（**ERC165**）とUX（**ERC2612**）を任意で拡張可能とし、実装と統合の双方での注意によって、安全で一貫した利用を実現します。

## 引用

Vu Nguyen (@mrenoon), Long Vuong (@UncleGrandpa925), Anton Buenavista (@ayobuenavista), "ERC-5115: SY Token [DRAFT]," Ethereum Improvement Proposals, no. 5115, May 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5115.

## 最後に

今回は「DeFi（分散型金融）で利回りを生むトークンを共通の方法で扱えるようにするための新しいトークン標準「**Standardized Yield（SY）**」を定めている**ERC5115**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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
