Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Superfluid for distributing rewards #83

Open
yu23ki14 opened this issue Aug 31, 2024 · 11 comments
Open

Add Superfluid for distributing rewards #83

yu23ki14 opened this issue Aug 31, 2024 · 11 comments
Assignees
Labels
Low Priority Low

Comments

@yu23ki14
Copy link
Member

Splitsをつかって分配しているが、Superfluidをつかったストリームでも分配できるようにする。

Splitsのように1つのコントラクトに資金をいれると自動で分配が始まるものに、DistributionPoolsというモジュールがあるのでそれを活用する。

@yu23ki14 yu23ki14 added the Low Priority Low label Aug 31, 2024
@mashharuki
Copy link
Collaborator

@aowheel ここです!

@mashharuki
Copy link
Collaborator

https://github.com/superfluid-finance/super-examples/tree/main/projects/gda-advertisement-auction
@aowheel これが参考になりそうです!!

@mashharuki
Copy link
Collaborator

以下、調べたメモ

Superfluidの「Distribution Pools」は、多人数に対して瞬時または継続的に資金を分配できる仕組みです。主に「即時配布」と「ストリーミング配布」の2種類があります。

即時配布: ガス代を固定して一度の取引で複数の受信者にトークンを送ることができます。
ストリーミング配布: 継続的に資金を送り、プール内のメンバーにトークンを自動的に分配します。
プールを作成し、プール管理者がメンバーに割り当てる「ユニット」に基づいてトークンを分配します。プールはERC20トークンと互換性があり、効率的かつ拡張可能です。

主な要素:

プール: トークンを比率に応じて分配するチャネル。
プール管理者: ユニットの設定や分配を管理。
プールメンバー: ユニットに基づいてトークンを受け取る。
この仕組みを使うことで、ガス代を抑えつつ効率的なトークン配布が可能です。

「Distribution Pools」は、Superfluidプロトコルの一部で、トークンを複数のメンバーに分配するスマートコントラクトです。メンバーは「ユニット」を保有し、これにより分配されるトークンの割合が決まります。分配の際に使用される「SuperTokenV1Library.sol」は、Superfluidの全ての機能にアクセスでき、トークンを効率的に分配するためのライブラリです。

プールメンバーは、プールに「接続」するか、トークンを「請求」することで自分のトークンを受け取れます。接続すれば、リアルタイムでトークンを受け取れ、請求はいつでも可能です。

トークン分配の仕組みは、各メンバーが保有するユニット数に基づいて計算されます。Solidityの制約で小数点が扱えないため、分配量が端数になる場合は切り捨てられます。プール設計時には、流量やトークン総量が十分大きいことを確認することが推奨されます。

主な関数には、プールの作成、ユニット数の更新、トークンの請求、接続、切断、そしてトークンの分配があります。

このガイドでは、Foundryフレームワークを使って DistributionContract のテストを実行する手順を説明しています。Superfluid コントラクトと同様の構造に従いながら、DistributionContract の特定の仕様に適応しています。

事前準備
SuperfluidコントラクトをFoundryでテストする前に、以下の手順で開発環境を整える必要があります。

プロジェクトディレクトリの作成と移動
mkdir superfluid-example && cd superfluid-example
新しいディレクトリを作成し、そのディレクトリに移動します。

Foundryプロジェクトの初期化
forge init
プロジェクトディレクトリ内にFoundryプロジェクトを初期化します。

Superfluidプロトコル依存関係のインストール
forge install superfluid-protocol-monorepo@dev --no-commit
Superfluidプロトコルの依存関係をGitHubリポジトリからインストールします。

OpenZeppelin Contractsのインストール
forge install [email protected] --no-commit
セキュリティが高いスマートコントラクトを構築するためのOpenZeppelin Contractsをインストールします。

コントラクトの概要
DistributionContract には、以下のような機能があります:

gainDaiX: fDAIをミントし、それをfDAIxにラップする機能。
createPool: 新しいSuperfluidプールを作成し、このコントラクトを管理者に設定。
updateMemberUnits: 特定のプールメンバーのユニットを更新。
createStreamToPool: このコントラクトからプールへのストリームを作成。
テスト環境のセットアップ
テスト環境を構築するには、既存のテストネット(例:Polygon Mumbai)をフォークするか、ローカルテストネットにSuperfluidプロトコルをデプロイする必要があります。

関数のテスト
各機能をテストするための手順も記載されています。例えば、gainDaiX 関数では、fDAIが適切にfDAIxにラップされているか確認し、createPool ではプールが正しく作成されているかを確認します。

このような手順を通じて、Superfluidプロトコルの各機能が期待通りに動作するかどうかをテストします。

@mashharuki mashharuki self-assigned this Oct 29, 2024
@mashharuki
Copy link
Collaborator

https://ethglobal.com/guides/introduction-to-superfluid-protocol-be10i#3-super-agreements

の約

  1. はじめに
    Superfluidとは? 通常、オンチェーンでトークンを移動させる際は、基本的なERC20転送を使用します。たとえば、100 DAIを転送すると、自分の残高は100減り、相手の残高が100増えます。 Superfluidのスマートコントラクトフレームワークはこれをさらに進化させ、Super Tokenと呼ばれる新しいトークン標準を導入しました。Super Tokenは基本的なERC20転送機能を拡張し、Super Agreement(スーパーアグリーメント)を追加します。このSuper Agreementにより、オンチェーンでトークンをより強力で柔軟に移動できるようになります! 最も人気のあるSuper Agreementは、Super Tokenのストリーミングを可能にする「Constant Flow Agreement(CFA)」です。他にも「Instant Distribution Agreement(IDA)」というSuper Agreementも提供しており、これを使えばスケーラブルな一対多の分配が可能です。このガイドでは、CFAを使ったお金のストリーミングに焦点を当てます。

Solidityでのお金のストリーミング スマートコントラクトがERC20トークンを転送できるのと同様に、Super Tokenをストリーミングできるスマートコントラクトも設定できます。このガイドでは、Super Tokenのストリーミングを設定する方法をわかりやすく解説していきます!

  1. Super Token
    Super Tokenとは? Super Tokenは、ERC20トークン標準をSuperfluidプロトコルに接続し、Super Agreementの機能を追加した拡張版です。このSuper Agreementにより、Super Tokenをストリームや即時分配といった強力な方法で移動させることができます。つまり、Super Tokenは従来のERC20トークンが持つ全ての機能に加えて、Superfluidによる新たな価値移転モード(例:お金のストリーミング)を備えています。 Super Tokenには「ラッパー」と「カスタム」の2種類があります。ラッパーSuper Tokenが一般的ですので、まずはこちらについて説明します。珍しいカスタムSuper Tokenについては、別のページをご覧ください。

ラッパーSuper Token ラッパーSuper Tokenは、既存のERC20トークンを「ラップ」してSuper Agreementの機能を持たせたものです。

ラッピングとアンラッピング ラッパーSuper Tokenを入手する際は、まずWrapper Super Tokenコントラクトで「upgrade(uint256 amount)」関数を使用します。これにより、指定した量のERC20トークンがウォレットから取り出され、同量のラッパーSuper Tokenが発行されます。つまり、通常のERC20トークンを手放し、「Super Token版」に変換したということです。 ラッパーSuper Tokenから元のERC20トークンに戻したい場合は、downgrade(uint256 amount)関数を使用してアンラッピングを行います。指定した量のSuper Tokenがバーンされ、同量の元のERC20トークンが返されます。

ラッパーSuper Tokenの命名規則は、元のトークンシンボルに「x」を付けたものです(例: USDC ➡ USDCx)。

トークンコントラクト
https://explorer.superfluid.finance/eth-sepolia/protocol

Solidityでのマネーストリーミング
Solidityでのお金のストリーミング SDK Coreを使って自分のEOAアカウント(個人ウォレット)から簡単にお金をストリーミングする方法を学びましたね。今度は、スマートコントラクト自身がトークンをストリーミングできるようにする方法を紹介します。

通常、スマートコントラクトでERC20トークンをtransfer関数で転送します👇

solidity
コードをコピーする
IERC20(tokenAddress).transfer(receiverAddress, amountToTransfer);
同じように、スマートコントラクトがSuper Tokenをストリーミングするには以下のようにします👇 ほとんど同じです!

solidity
コードをコピーする
ISuperToken(superTokenAddress).createFlow(receiverAddress, perSecondflowRate);
ただし、コントラクトがこのようにお金をストリーミングできるように、事前にいくつか設定が必要です。以下の手順を見ていきましょう!

基本例 - FlowSenderコントラクト コントラクトがどのようにストリーミングでお金を送れるかを示すために、FlowSenderというシンプルなコントラクトを使います。FlowSenderは自らにfDAIxを資金提供し、指定したアドレスに対してストリームを作成・更新・削除することができます。

コードの説明

Superfluidのセットアップ まず、Superfluidプロトコルとやり取りするために必要なインポートを行います:

solidity
コードをコピーする
import {IFakeDAI} from "./IFakeDAI.sol";
import { ISuperfluid, ISuperToken } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol";
import { SuperTokenV1Library } from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol";
その後、FlowSenderコントラクト内で以下のコードを使い、SuperTokenV1Libraryをセットアップします:

solidity
コードをコピーする
using SuperTokenV1Library for ISuperToken;
コントラクトにSuper Tokenを取得させる gainDaiX関数を呼び出して行います。この関数はFlowSenderコントラクトにfDAIを10,000枚発行し、それをfDAIxにラップします。

solidity
コードをコピーする
function gainDaiX() external {
// fDAIxトークンの基になるfDAIアドレスを取得
IFakeDAI fdai = IFakeDAI( daix.getUnderlyingToken() );

// 10,000 fDAIをミント
fdai.mint(address(this), 10000e18);
// fDAIxコントラクトがfDAIを使えるように許可
fdai.approve(address(daix), 20000e18);
// fDAIをfDAIxにラップ
daix.upgrade(10000e18);

}
ストリームの作成 createStream関数で、fDAIxのストリームをコントラクトから任意のアドレスに送ります。

solidity
コードをコピーする
function createStream(int96 flowRate, address receiver) external {
// ストリームを作成
daix.createFlow(receiver, flowRate);
}
FlowSenderのコンパイルとデプロイ Compileタブに移動してFlowSenderコントラクトをコンパイルします。

MetamaskをGoerli Testnetに接続し、Environmentを「Injected Provider - Metamask」に設定します。

Deployタブで次のパラメータでデプロイします:

_DAIX - 0xF2d68898557cCb2Cf4C10c3Ef2B034b2a69DAD00 fDAIxのアドレス(Mumbai Testnet用のfDAIトークンのラッパーSuper Token)
fDAIxでFlowSenderをロード gainDaiX関数を呼び出すと、コントラクトに10,000 fDAIxが追加されます。

fDAIxのストリームを送信 createStream関数を使用し、受信者アドレスと毎秒のフロー率を指定します。フロー率は常に1秒あたりのwei単位です。たとえば、コントラクトが毎時10 fDAIxをストリーミングする場合、以下のようにします:

10 fDAIx/時間
= 10 * (1018) fDAIx / 時間
= 10 * (10
18) fDAIx / (60秒 * 60分)
= 2777777800000000
ストリームの確認 トランザクションが完了したら、Superfluidコンソールにアクセスし、検索バーにアドレスを貼り付けて、FlowSenderコントラクトの残高がリアルタイムで変化する様子を確認しましょう!

@mashharuki
Copy link
Collaborator

スクリーンショット 2024-11-24 13 52 08

やっと createStreamできた!!!

@mashharuki
Copy link
Collaborator

https://docs.superfluid.finance/docs/protocol/money-streaming/examples/example1

↑ FlowSenderの考え方を応用した FlowSpliterに関する説明。

@mashharuki
Copy link
Collaborator

スクリーンショット 2024-12-03 22 03 26 スクリーンショット 2024-12-03 21 58 51 ↑ なんとか distributionを試せました!!

@mashharuki
Copy link
Collaborator

ですが、課題があります。

独自のSuperTokenで行けるかってのとTobanの中に組み込めるかが課題ですね・・。
superfuildのライブラリの方が不安定すぎるのでそこだけ要検証です・・

superfuildのライブラリの方、openzeppelinの最新バージョンに対応していないっぽくて自分で追加したりしてようやく動いている状態です・・。

https://github.com/mashharuki/SuperfluidRepo/tree/main/superfluid-example
↑こちらのリポジトリで試してました。

foundryで動かしているのでhardhatに移行させるのが少し大変かも・・・。

@mashharuki
Copy link
Collaborator

チームに確認したいこと。

・独自のSuperTokenを作るために必要なことの確認
・ライブラリが不安定すぎるのでなんとかしてほしい・・
・hardhat用の開発テンプレートキットなどはないか?

@mashharuki
Copy link
Collaborator

場合によっては、他のフレームワークを使うことを検討する。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Low Priority Low
Projects
None yet
Development

No branches or pull requests

2 participants