Page cover image

💻 アルパカファイナンスとの連携

アルパカファイナンスとの連携

アルパカファイナンスでは、DeFiアプリケーションとエンドユーザがそのコアプロトコルと連携することができます。

このドキュメントの目的は、エコシステムの全体的なセキュリティを確保するために、開発者が私たちのプロトコルと連携することを支援することです。

まず、私たちのプロトコルをよりよく理解したい場合は、ここで私たちの契約文書を確認することができます。

重要な統計情報

私たちのフロントエンドで使用されるAPIを以下で公開します。必要な情報はすべて提供しているので、これを利用して私たちの情報と自動的に同期することができます。

AF1.0:

AF2.0:

APIに含まれる情報の一例:

  1. すべてのレンディングプールとその統計情報(例:APR、TVL、供給と借入、ibToken価格)

  2. すべての(ファーム)とその統計(例:APR、TVL)

  3. すべての自動化ヴォールトとその統計(例:APY、AVシェア価格)

スマートコントラクトの連携

ここでは、スマートコントラクトから直接アルパカファイナンスと連携する方法を説明します。

レンディング

アルパカファイナンスでは、ユーザーが暗号資産を私たちのレンディングプールに預け入れることで、その暗号資産の利息収入を得ることができます。

これらの資産は、レバレッジをかけるためにファーマーに提供されます。BSC上に展開されているEVM互換のスマートコントラクトであれば、アルパカファイナンスのレンディングプロトコルと連携することができます。

トークンをアルパカファイナンスのプールに預け入れるには、まず、利用可能なプールのリストとそれに対応するトークンを取得する必要があります。

  • 全プールのコントラクトアドレスの一覧はこちらをご覧ください。

プールに入金する前に、入金者となるスマートコントラクトはまず入金するトークンの支出許容量を承認する必要があります。これにより、アルパカのスマートコントラクトは、送信者からトークンを取得できるようになります。

// JavaScript
import { ERC20 } from '../typechain/ERC20'
import { MaxUint256 } from '@ethersproject/constants'

...

const yourSmartContractAddress = 'xxx'
tokenERC20.approve(yourSmartContractAddress, MaxUint256);

上記のJavaScriptのスニペットは、トークンの支出許容量を最大にして承認するための簡単な流れです。なお、MaxUint256を使用するとセキュリティ上のリスクが生じる可能性があるため、ユーザーが入力した正確なトークン量を使用することを推奨します。

預け入れの実行は、deposit メソッドを呼び出し、 amountToken パラメータに預け入れ額を指定することで行われます。

amountTokenのデータ型はuint256で、このパラメータは預け入れるトークンの小数に合わせてフォーマットされていなければなりません(例えば,BNBは18小数を使用するので、1 BNB = 10000000000000000000または1 * 1e18)。預け入れるトークンがBNBの場合、プールはBNBのwBNBへのラッピングを処理しますが、トランザクションにはネイティブトークンとして送られた十分なBNBが含まれていなければなりません。

// Solidity
address vaultContractAddress = '0xd7D069493685A581d27824Fc46EdA46B7EfC0063'; // BNB Vault
if (msg.value == 0) { // if no native token is sent, then it is a ERC20/BEP20 token deposit
	IERC20(tokenAddess).safeTransferFrom(address(msg.sender), address(this), amountToken);
}
// Allow transfer to vault
SafeToken.safeApprove(tokenAddess, vaultContractAddress, amountToken);
// Deposit to vault
IVault(vaultContractAddress).deposit(amountToken);

預け入れが成功した場合、プールは利付トークン(ibTokens)を発行し、発行されたトークンを呼び出し元に返します。利子付きトークンの設計上、返却された利子付きトークンの額は、供給されたトークンの量とは一致しませんのでご注意ください。

預け入れメソッドの呼び出し元は、プールへの預け入れについて、ユーザーのシェアを正しく把握する必要があります。詳細な説明については、「有利子トークンの計算」セクションを参照してください。

貸し出しによる利子はibトークン内に発生します。貸し出しによる利益を得るためには、ibトークンを引き出し元のトークンに交換する必要があります。引き出し時のibTokenの交換価格が高くなっていることに気づくと思いますが、これは利子がすでに発生していることを示しています。そのため、引き出し時にはより多いトークンを受け取ることができます。

プールからトークンを引き出すためには、引き出すibトークンの量をVaultコントラクトのWithdrowメソッドに供給する必要があります。

// Solidity
address vaultContractAddress = '0xd7D069493685A581d27824Fc46EdA46B7EfC0063'; // BNB Vault
IVault(vaultContractAddress).withdraw(ibTokenAmount);

その後トークンは呼び出し元に戻されます。返されたトークンがBNBの場合、VaultコントラクトはWBNBをBNBにアンラップして戻します。

利付きトークンの計算

Interest Bearing Token(ibトークン)は、預け入れする人のプールのシェアを表すトークンです。ibトークンは、時間の経過とともに貸し出しで得た利息が発生します。アルパカファイナンスのプールを利用しようとするDeFiプロトコルは、実際のユーザーのプールのシェアを反映するために、ibトークンの計算を正しく理解し、実装する必要があります。

したがって、金庫が最初にオープンしたときには、ibトークンと元のトークンの比率は 1 : 1 にしかなりませんが、その後は貸し出し利子が発生するため、ibトークンの価値は上昇し続けます(元のトークンに対するibトークンの価値は、一方的に上昇するだけです。価値が下がることはありません)

例えば、1ibBNB=1.0292BNBとすると、1.0292BNBを預けると1ibBNBが返ってくることになります。一方、1 ibBNBを換金すると、1.0292 BNBが返ってきます。ibBNBを償還することによる追加のBNBは、未収の利子によるものです。

アルパカファイナンスのレンディングプールと連携するDeFiプロトコルでは、プールの預け入れに対するユーザーの取り分を正確に計算する必要があるため、このibトークンの価値の基本的なしくみを理解することは非常に重要です。

これに失敗すると、セキュリティ上のリスクや金銭的な損失が発生する可能性があります。これは、bEarn.fiおよびValueDeFiへの攻撃の場合で、これらのプロトコルは常にibTokensを元のトークンと 1 : 1 の比率で扱っていました(bEarn.fiおよびValueDefiへの攻撃の分析を参照)

また、アルパカはフラッシュローンとは連携していませんが、アルパカ以外の外部プールでは、フラッシュローン攻撃などの攻撃から ibトークンの価格が操作されるリスクがあります。何の準備もしていなければ、攻撃者の取引の範囲内でibトークンの価格が大幅に変更される可能性があります。

そのため、スマートコントラクトの計算によるibトークンの価格に頼るだけでは不十分です。私たちは、上記のような攻撃を防ぐために、ibトークンとその元のトークンの現在の比率をフィードする価格オラクルをプロジェクトに持つことを推奨します。

そこで、ibトークンの価格を計算する最も安全で正しい方法をご紹介します。

スマートコントラクトからの直接計算

スマートコントラクトからibトークンの価格を計算するのは最もシンプルな方法ですが、堅牢性のためには、それだけに頼ってはいけません。

// Solidity
address vaultContractAddress = '0xd7D069493685A581d27824Fc46EdA46B7EfC0063'; // BNB Vault
IVault vault = IVault(vaultContractAddress);
uint256 ibTokenAmount = ...;
uint256 ibTokenPrice = vault.totalToken()).div(vault.totalSupply();
uint256 underlyingTokenAmount = ibTokenAmount.mul(ibTokenPrice);

上記のスニペットは、対応するプールからtotalTokentotalSupplyの値を取得して、ibトークンの価格を計算する様子を示しています。.

アルパカAPIからibトークンの価格を取得する

アルパカファイナンスは、エンドポイント/ibTokensGET RESTリクエストを送信して任意のibトークン価格を取得することで、現在のibトークン価格を取得するためのAPIを提供しています。アルパカAPIとの連携には認証が必要ですので、このサービスをご利用になりたい場合はお問い合わせください。

APIからの結果例は以下の通りです。

{
    "status": {
        "code": 1000,
        "messages": [
            "OK"
        ]
    },
    "data": [
        {
            "symbol": "ibALPACA",
            "baseTokenPerShare": "1.051108636596531492",
            "lendingApr": "0.0003638488758058",
            "stakingApr": "0.0"
        },
        {
            "symbol": "ibBNB",
            "baseTokenPerShare": "1.025808940627339553",
            "lendingApr": "9.7785294844178225",
            "stakingApr": "316693.265280905443641"
        },
        {
            "symbol": "ibBUSD",
            "baseTokenPerShare": "0.972337256352625836",
            "lendingApr": "0.368330890561667",
            "stakingApr": "2269.786601379154162"
        },
        {
            "symbol": "ibUSDT",
            "baseTokenPerShare": "0.913094694500682622",
            "lendingApr": "0.0012775198722327",
            "stakingApr": "0.0"
        },
        {
            "symbol": "ibBTCB",
            "baseTokenPerShare": "1.000006160536069502",
            "lendingApr": "6.5534019786376696",
            "stakingApr": "0.0"
        },
        {
            "symbol": "ibETH",
            "baseTokenPerShare": "0.999463386510494271",
            "lendingApr": "0.0000004209960912",
            "stakingApr": "0.0"
        }
    ]
}

アルパカのAPIから取得した価格は、価格オラクルを使用してスマートコントラクトに供給する必要があります。スマートコントラクトの呼び出しへの入力を介して価格を供給すると、クライアントからのインジェクション攻撃に対して脆弱になります。そのようなことをしないように強くお勧めします。シンプルなプライスオラクルの例はこちらでご覧いただけます。信頼できる価格オラクルを使用することで、ibトークンの価格データの整合性と信頼性を確保することができます。

スマートコントラクトの計算とアルパカAPIの両方からibトークンの価格を取得することを強くお勧めします。これらの2つの価格データのソースを比較して、データの異常の可能性を防ぐ必要があります。2 つのソースの比較が大きく異なる場合、その価格データは拒否されるべきです。

要約すると、ibトークンの価格を計算する最も安全なプロセスは以下の通りです。

  1. 独自のコントラクトでibトークンの価格を計算します。

  2. オフチェーンのオラクルか、アルパカのAPIからibトークンの価格を得ます。

  3. 1と2を比較します。その差がn%以上であれば、その取引を元に戻します。

アルパカのAPIは、現在、プロトコルと機関を対象としたホワイトリストのみアクセス可能となっています。アクセスをご希望の方は、requests@alpacafinance.org までご連絡ください。

ステーキング

計画どおり、ALPACA報酬の配布は終了しました。以下に記載するステーキング関連情報は参考情報です。

アルパカファイナンスはユーザーにステーキングの機会を提供します。私たちのステーキングプールで利付きトークンと一部のLPトークンはステーキングすることで、ALPACAトークンの形で追加の利回りを受け取ることができます。

資金を入金してibトークンを受け取った場合、利用可能な最大の報酬を得るために、ibトークンはこれらのプールにステーキングすることをお勧めします。

アルパカファイナンスのStakeプールにトークンをステーキングするには、まずプールのリストとそれに対応するトークンを取得する必要があります。

すべてのプールのコントラクトアドレスの詳細なリストについてはこちらをご覧ください。プールのコントラクトは、当社のコードベースでは一般的にFairlaunchと呼ばれています。

ステーキングの実行は、Depositメソッド呼び出すことで行います。パラメータは以下の通りです。

  • _for は入金者のアドレスです。

  • _pid は、ステーキングプールの ID です。

  • _amount は,預けるトークンの量をuint256の小数で表したものです(例えばibBNBは18の小数を使うので、1 ibBNB = 10000000000000000000または1 * 1e18

// Solidity
address fairlaunchContractAddress = '0xA625AB01B08ce023B2a342Dbb12a16f2C8489A8F'; // ibBNB pool
IFairLaunch fairlaunch = IFairLaunch(fairlaunchContractAddress);
fairlaunch.deposit(msg.sender, poolId, amount);

ステーキングシェアの情報は、スマートコントラクトの状態で保存されます。ステーキングによるトークンの発行はありません。ユーザーのシェアは、Fairlaunch コントラクトから userInfo メソッドを呼び出すことで取得できます。

ステーキングによる報酬は自動的には入金されず、手動で収穫しなければなりません。しかし、ステーキングされたプールで入金または出金を行うと、呼び出し側に保留されている報酬が自動的に収穫されます。

ステーキングプールから報酬を収穫するには、呼び出し側はFairlaunchコントラクトからharvestメソッドを呼び出し、プールIDを指定しなければなりません。

// Solidity
address fairlaunchContractAddress = '0xA625AB01B08ce023B2a342Dbb12a16f2C8489A8F'; // ibBNB pool
IFairLaunch fairlaunch = IFairLaunch(fairlaunchContractAddress);
fairlaunch.harvest(poolId);

ステーキングされたトークンをプールから引き出すには、ユーザーのシェア分の金額をFairlaunchコントラクト契約のwithdrowメソッドに供給する必要があります。

// Solidity
address fairlaunchContractAddress = '0xA625AB01B08ce023B2a342Dbb12a16f2C8489A8F'; // ibBNB pool
IFairLaunch fairlaunch = IFairLaunch(fairlaunchContractAddress);
fairlaunch.withdraw(msg.sender, poolId, amount);

ステーキングされたトークンは呼び出し側に返却され、保留中の報酬も自動的に収穫されます。

アルパカファイナンスとのテスト

現在、テストネット環境でのサポートは行っておりません。メインネットからフォークしてテストすることを推奨していますが、これはTenderly's Forkで簡単に実現できます。すべての関連情報およびアドレスは、https://github.com/alpaca-finance/bsc-alpaca-contract/blob/main/.mainnet.json を参照してください。

Last updated