hackdays-io / toban

MIT License
17 stars 3 forks source link

Add Superfluid for distributing rewards #83

Open yu23ki14 opened 2 months ago

yu23ki14 commented 2 months ago

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

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

mashharuki commented 1 month ago

@aowheel ここです!

mashharuki commented 1 month ago

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

mashharuki commented 2 weeks ago

以下、調べたメモ

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 openzeppelin-contracts@v4.9.3 --no-commit セキュリティが高いスマートコントラクトを構築するためのOpenZeppelin Contractsをインストールします。

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

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

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

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

mashharuki commented 1 week ago

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

mashharuki commented 1 week ago

https://docs.superfluid.finance/docs/concepts/superfluid

https://explorer.superfluid.finance/

https://www.superfluid.finance/ecosystem