💻Integrating With Alpaca Finance
Integrating with Alpaca Finance
Alpaca Finance allows DeFi applications and end users to integrate with its core protocol. The purpose of this document is to assist developers in integrating with our protocol to ensure overall security for the ecosystem.
If you would like to first have a better understanding of our protocol, you can review our contract documentation here.
Important Statistics
The following public APIs contain all the necessary information used in our frontend, so you may use them as sources that will be automatically synchronized with us.
AF1.0:
AF2.0:
Example of information included in the APIs:
All lending pools and their stats e.g., APR, TVL, Supply and Borrow, ibToken price
All workers (farm) and their stats e.g., APR, TVL
All Automated Vaults and their stats e.g., APY, AV Share Price
Smart Contract Integration
This section describes how to integrate with Alpaca Finance directly from a smart contract.
Lending
Alpaca Finance allows users to earn interest income on crypto assets by depositing them into our deposit vaults. These assets are then offered to yield farmers for leveraging up their positions. Any smart contract which is EVM compatible and deployed on BNB Chain can integrate with Alpaca Finance's lending protocol.
To deposit the base token into Alpaca Finance's vaults, the list of available vaults and their corresponding base tokens should first be acquired.
Please see here for the detailed list of all vault contract addresses.
Before a deposit can be made to a vault, the smart contract which acts as a depositor must first approve the spending allowance of the base token to be deposited. This will provide Alpaca's Smart Contract the ability to obtain tokens from the sender.
The above JavaScript code snippet is a simplified workflow on how to approve token spending allowance with maximum possible amount. Please note that using MaxUint256
could introduce security risk, using the exact token amount input by user is recommended.
Performing a deposit is done by calling the deposit
method and specifying the deposit amount in the amountToken
parameter. The amountToken
data type is uint256
and this parameter must be formatted to the decimals of the deposit token (for example, BNB uses 18 decimals, 1 BNB = 10000000000000000000
or 1 * 1e18
). For the case where the deposit token is BNB, the vault will handle the wrapping of BNB into wBNB, but the transaction must include enough BNB sent as the native token.
If the deposit is successful, the vault will mint interest-bearing tokens (ibTokens) and return those minted tokens back to the caller. Please note that the amount of the returned interest-bearing token will not be equal to the supplied base token amount due to the design of interest-bearing tokens. The caller of the deposit
method must correctly keep track of the users' shares for deposits in vaults, please see the Interest Bearing Token Calculation section for a detailed explanation.
The interest from lending will accrue to the ibTokens. To realize the gains from lending, the ibTokens must be withdrawn, redeeming back the base token + collected interest. You will notice that the exchange price of the ibToken would be higher at withdrawal, which indicates that interest has already accrued. Therefore, you will receive additional base tokens upon withdrawing.
To redeem the base tokens from the vault, the amount of the ibTokens to be withdrawn must be supplied to the withdraw
method in the Vault
contract.
The base tokens will then be returned back to the caller. If the returned token is BNB, the Vault contract will unwrap WBNB back into BNB.
Interest Bearing Token Calculation
An Interest Bearing Token (ibToken) is the token which represents the vault share of the depositor. ibTokens will accrue interest received from lending over time. Any DeFi protocol wishing to utilize Alpaca Finance's vaults should understand and implement the calculation of ibTokens correctly to reflect the actual users' shares of the vault.
Hence, the ratio between an ibToken and the actual base token will only be 1:1 when the vault first opens, after which the ibToken's value will continue to increase as lending interest accrues (The value of an ibToken relative to the base token will only move one-way upwards. The value cannot decrease). For example, let's assume the price: 1 ibBNB = 1.0292 BNB
which means a deposit of 1.0292 BNB will get 1 ibBNB in return. On the other hand, redeeming 1 ibBNB will get 1.0292 BNB in return. The additional BNB from redeeming ibBNB are from the accrued interest.
Understanding this one fundamental mechanic of ibTokens' values is crucial, since a DeFi protocol integrating with Alpaca Finance's lending vaults might need to accurately calculate the users' shares of the vault deposit. Failure to do so could impose security risk and financial loss. This was the case for the attacks on bEarn.fi and ValueDeFi in which these protocols always treated ibTokens as having a 1:1 ratio with the underlying token (read the analysis of the attacks on bEarn.fi and ValueDefi).
In addition, although Alpaca does not work with flash loans, in an external non-Alpaca vault, there could be a risk of ibToken price manipulation from an attack such as a flash loan attack. If unprepared, the price of an ibToken could be drastically changed inside the scope of an attacker's transaction. That's why, relying on the ibToken price from smart contract calculation alone is not enough. We recommend the project to have a price oracle feeding the current ratio of ibTokens vs its base token to prevent such an attack mentioned above.
Therefore, we will show you the safest and correct way to calculate the prices of ibTokens.
Direct calculation from smart contract
Calculating ibToken token price from the smart contract is the simplest way, but for robustness, it must not be the only method you rely on.
The above code snippet demonstrates an ibToken price calculation from retrieving the value of totalToken
and totalSupply
from the corresponding vault.
Retrieving ibToken price from Alpaca API
Alpaca Finance has provided an API to retrieve the current ibToken prices by sending a GET
REST request to the endpoint /ibTokens
to retrieve any ibToken price.
The sample result from the API is as follow:
The price retrieved from Alpaca's API should be supplied to the smart contract using a price oracle. Supplying the prices via an input to a smart contract call will be vulnerable to an injection attack from the client. We strongly advised against doing that. An example of a simple price oracle could be seen here. By using a trusted price oracle, you can ensure the integrity and reliability of the ibToken price data.
We strongly recommend retrieving the ibToken price from both smart contract calculation and Alpaca API. These two sources of price data should be compared to prevent any possible data anomaly. If the comparison between the two sources differs significantly, the price data should be rejected.
In summary, the most secure process to calculate ibToken prices is the following:
Calculate ibToken prices in your own contracts.
Use an off-chain oracle for ibToken prices or pull those prices from Alpaca's API.
Compare 1 and 2. If the difference is more than n% then revert the transaction.
Staking
As per emission schedule, ALPACA emission rewards have now concluded. Thus, the Staking-related information provided below is for reference purposes only and may no longer be relevant due to the suspension of ALPACA staking rewards.
Alpaca Finance provides staking opportunities to users. Interest-bearing tokens and selected LP tokens are available for staking in our staking pools to receive additional yields in the form of ALPACA tokens. If you have deposited funds and received ibTokens, we recommend you to stake those tokens into these pools to earn the maximum available rewards.
To stake the tokens into Alpaca Finance's staking pools, the list of pools and their corresponding staking tokens should first be acquired. Please see here for an in-depth list of all pool contract addresses. The contract of the pools is generally called Fairlaunch
in our codebase.
Performing staking is done by calling the deposit
method. The parameters are as followed:
_for
is the address of the depositor._pid
is the id of the staking pool._amount
is the amount of the token to be deposited inuint256
expressed in its decimals (for example, ibBNB uses 18 decimals, 1 ibBNB =10000000000000000000
or1 * 1e18
)
The information of the staking share will be stored inside the smart contract state. There will be no token issued from staking. The share of a user can be retrieved by calling the userInfo
method from the Fairlaunch
contract.
The rewards from staking are not automatically credited and must be manually harvested. However, performing a deposit or withdraw on the staked pools will automatically harvest any pending rewards to the caller. To harvest rewards from a staking pool, the caller must call the harvest
method from the Fairlaunch
contract and supply the pool id.
To withdraw the staking tokens from the pool, the amount of the user's share must be supplied to the withdraw
method in the Fairlaunch
contract.
The staking tokens will be returned to the caller and any pending rewards will also be automatically harvested.
Testing with Alpaca Finance
Currently, we do not offer support for testnet environment. We recommend testing by forking from mainnet, which can be easily accomplished through Tenderly's Fork. For all relevant information and addresses, please refer to https://github.com/alpaca-finance/bsc-alpaca-contract/blob/main/.mainnet.json
Last updated