# Yield Aggregator
The yield aggregator is Rari's product that enables anyone to instantly deposit a supported asset and receive an interest generating one.
# Overview
# R(X)PT (Rari (X) Pool Tokens)
Each user's share of a Rari Pool is represented by their R(X)PT (Rari (X) Pool Token) balance, an example being the Rari Stable Pool being represented by RSPT aka Rari Stable Pool Token. When you deposit funds to a Rari Pool, an equivalent amount (value-wise) of pool tokens is minted to your account. When you withdraw funds from the pool, the equivalent amount of value in the pool token is burned from your account. As soon as you deposit, you start earning yield. Essentially, Rari pool tokens holdings and yield are split up across the pool token holders proportionally to their balances.
# Deposits
Only certain stablecoins are accepted for direct deposits (direct meaning without exchange to an accepted currency). To deposit another currency, you must exchange your funds before depositing. Fortunately, Rari can exchange and deposit your funds in the same transaction via 0x (opens new window) and/or mStable (opens new window) (please be aware that exchanges via 0x are subject to slippage due to price spread as well as an ETH protocol fee, and exchanges via mStable are subject to a small denominational percentage fee, but can avoid slippage and even get you a bonus).
See Contract Usage section below for more information on how to deposit via the smart contracts and API section below for a detailed reference on the smart contract methods involved. See the Rari SDK for easy implementation and the web client for easy usage.
# Withdrawals
Only the stablecoins currently held by the Rari Stable Pool are available for direct withdrawals. To withdraw another currency, you must exchange your funds after withdrawing. Fortunately, Rari can withdraw and exchange your funds in the same transaction via 0x (opens new window) and/or mStable (opens new window) (please be aware that exchanges via 0x are subject to slippage due to price spread as well as an ETH protocol fee, and exchanges via mStable are subject to a small denominational percentage fee, but can avoid slippage and even get you a bonus).
See the Contract Usage section belowfor more information on how to withdraw via the smart contracts and API section below for a detailed reference on the smart contract methods involved. See the Rari SDK for easy implementation and the web client for easy usage.
# Structure
The Rari Stable Pool is composed of 5 user-facing smart contracts in total (see DEPLOYED.md
(opens new window) for deployed addresses):
RariFundManager
is the Rari Stable Pool's main contract, handling deposits, withdrawals, USD balances, interest, fees, etc.RariFundController
holds supplied funds and is used by the rebalancer to deposit and withdraw from pools and make exchanges.RariFundToken
is the contract behind the Rari Stable Pool Token (RSPT), an ERC20 token used to internally account for the ownership of funds supplied to the Rari Stable Pool.RariFundPriceConsumer
retrieves stablecoin prices from Chainlink's public price feeds (used byRariFundManager
andRariFundController
).RariFundProxy
includes wrapper functions built on top ofRariFundManager
: exchange and deposit, withdraw and exchange, and deposit without paying gas via the Gas Station Network (GSN).
A rebalancer controls which pools hold which currencies at any given time but only has permission to move funds between pools and exchange currencies, not withdraw funds elsewhere.
# Security
Rari's Ethereum-based smart contracts are written in Solidity and audited by Quantstamp (opens new window) (as well as various other partners) for security. Rari does not have control over your funds: instead, the Ethereum blockchain executes all secure code across its entire decentralized network (making it very difficult and extremely costly to rewrite history), and your funds are only withdrawable by you.
The rebalancer only has permission to move funds between pools and exchange currencies, not withdraw funds elsewhere. Losses due to exchange slippage in a 24-hour period are limited proportionally to the total supply for security since 0x orders can come from anywhere. However, the rebalancer can approve any amount of funds to the pools and exchanges integrated.
Please note that at the moment, smart contract upgrades are approved via a multisig federation controlled by various trusted parties. Each of the upgrades need to be voted on by governance at: vote.rari.capital for them to go live.
Please note that using our web client online at app.rari.capital (opens new window) is not nearly as trustworthy as downloading, verifying, and using it offline. Lastly, the rebalancer can only rebalance funds to different pools and currencies (with limits on slippage).
# Contract Usage
The following document contains instructions on common usage of the Rari Stable Pool smart contracts' APIs.
- See API section below for a more detailed API reference on
RariFundController
,RariFundManager
,RariFundToken
,RariFundPriceConsumer
, andRariFundProxy
. - See EIP-20: ERC-20 Token Standard (opens new window) for reference on all common functions of ERC20 tokens like RSPT.
- Smart contract ABIs are available in the
abi
properties of the JSON files in thebuild
folder.
If you're using JavaScript, don't waste your time directly integrating our smart contracts: the Rari JavaScript SDK (opens new window) makes programmatic deposits and withdrawals as easy as just one line of code!
# Stable Pool APY
- Get current raw APY (before fees):
- Get raw currency/subpool allocations (including unclaimed fees on interest):
(string[], uint256[], RariFundController.LiquidityPool[][], uint256[][], uint256[]) RariFundProxy.getRawFundBalancesAndPrices()
returns an array of currency codes, an array of corresponding fund controller contract balances for each currency code, an array of arrays of pool indexes for each currency code, an array of arrays of corresponding balances at each pool index for each currency code, and an array of prices in USD (scaled by 1e18) for each currency code. - Multiply the APY of each pool of each currency by its fund controller balance (converted to USD).
- Divide the sum of these products by the sum of all fund controller contract balances and pool balances of each currency (converted to USD) to get the current Stable Pool APY.
- Get raw currency/subpool allocations (including unclaimed fees on interest):
- Get current APY (after fees): subtract the product of the current raw APY and
uint256 RariFundManager.getInterestFeeRate()
divided by 1e18 from the current raw Stable Pool APY. - Get APY over time range (after fees):
- Get RSPT exchange rates at start and end of time range: divide
RariFundManager.getFundBalance()
byRariFundToken.totalSupply()
to get the exchange rate of RSPT in USD (scaled by 1e18). - Divide the ending exchange rate by the starting exchange rate, raise this quotient to the power of 1 year divided by the length of the time range, and subtract one to get the Stable Pool APY over this time range.
- Get RSPT exchange rates at start and end of time range: divide
# My Balance and Interest
- Get my USD balance supplied:
uint256 RariFundManager.balanceOf(address account)
returns the total balance in USD (scaled by 1e18) supplied to the Rari Stable Pool byaccount
. - Get my interest accrued: Subtract total deposits and transfers in (in USD) and add total withdrawals and transfers out (in USD) from
uint256 RariFundManager.balanceOf(address account)
.
# Deposit
User chooses to deposit one of our directly supported tokens (DAI, USDC, USDT, TUSD, BUSD, and sUSD), ETH, or one of the tokens listed by the 0x swap tokens API (see documentation (opens new window) and endpoint (opens new window)) in an amount no greater than the balance of their Ethereum account.
User calls
string[] RariFundManager.getAcceptedCurrencies()
to get an array of currency codes currently accepted for direct deposit to the Stable Pool.If desired deposit currency is accepted:
Generally, user simply approves tokens and deposits them:
- User approves tokens to
RariFundManager
by callingapprove(address spender, uint256 amount)
on the ERC20 contract of the desired input token wherespender
isRariFundManager
(to approve unlimited funds, setamount
touint256(-1)
). - Deposit with
bool RariFundManager.deposit(string currencyCode, uint256 amount)
- User approves tokens to
To avoid paying gas, if the user's Ethereum account has no past deposit, the deposit amount is >= 250 USD, and the ETH balance returned by
RelayHub(0xd216153c06e857cd7f72665e0af1d7d82172f494).balanceOf(0xb6b79d857858004bf475e4a57d4a446da4884866)
is enough to cover the necessary gas, the user can submit their transaction via the Gas Station Network (GSN):
User approves tokens to
RariFundProxy
by callingapprove(address spender, uint256 amount)
on the ERC20 contract of the desired input token wherespender
isRariFundProxy
(to approve unlimited funds, setamount
touint256(-1)
).To get the necessary approval data (a signature from our trusted signer allowing the user to use our ETH for gas), POST the JSON body
{ from, to, encodedFunctionCall, txFee, gasPrice, gas, nonce, relayerAddress, relayHubAddress; }
to
https://app.rari.capital/checkSig.php
- Note that
checkSig.php
may go offline at some point in the future, in which case the user should deposit normally as described above.
- Note that
User calls
bool RariFundProxy.deposit(string currencyCode, uint256 amount)
via the Gas Station Network (GSN).
If desired deposit currency is not accepted, get exchange data from mStable (preferably) and/or 0x:
If desired deposit currency is DAI, USDC, USDT, TUSD, or mUSD, until the user fulfills their entire deposit, exchange to any depositable currency among DAI, USDC, USDT, TUSD, or mUSD via mStable and deposit:
- Get exchange data from mStable:
- If desired deposit currency is DAI, USDC, USDT, or TUSD, check
(bool, string, uint256, uint256) MassetValidationHelper(0xabcc93c3be238884cc3309c19afd128fafc16911).getMaxSwap(0xe2f2a5c287993345a840db3b0845fbc70f5935a5, address _input, address _output)
. If the first returned value istrue
, the user can exchange a maximum input amount of the third returned value. - If desired deposit currency is mUSD, check
(bool, string, uint256 output, uint256 bassetQuantityArg) MassetValidationHelper(0xabcc93c3be238884cc3309c19afd128fafc16911).getRedeemValidity(0xabcc93c3be238884cc3309c19afd128fafc16911, uint256 _mAssetQuantity, address _outputBasset)
. If the first returned value istrue
, the user can exchange a maximum input amount ofbassetQuantityArg
(the fourth returned value).
- If desired deposit currency is DAI, USDC, USDT, or TUSD, check
- User calls
bool RariFundProxy.exchangeAndDeposit(string inputCurrencyCode, uint256 inputAmount, string outputCurrencyCode)
to exchange and deposit.
- Get exchange data from mStable:
If exchange via mStable is not possible (or if the user wants to exchange the rest of their deposit via 0x if mStable cannot exchange it all), retrieve order data from 0x:
User retrieves data from 0x swap quote API (see documentation (opens new window) and endpoint (opens new window)) where:
sellToken
is their input currencybuyToken
is a directly depositable currency to which the desired deposit currency will be exchangedsellAmount
is the input amount to be sent by the user
User approves tokens to
RariFundProxy
by callingapprove(address spender, uint256 amount)
on the ERC20 contract of the desired input token wherespender
isRariFundProxy
(to approve unlimited funds, setamount
touint256(-1)
).User calls
bool RariFundProxy.exchangeAndDeposit(address inputErc20Contract, uint256 inputAmount, string outputCurrencyCode, LibOrder.Order[] orders, bytes[] signatures, uint256 takerAssetFillAmount)
where:
orders
is the orders array returned by the 0x APIsignatures
in an array of signatures from the orders array returned by the 0x APItakerAssetFillAmount
is the input amount sent by the user
# Withdraw
- User ensures that their account possesses enough USD (represented internally by RSPT) to make their withdrawal.
- User calls
uint256 RariFundManager.getRawFundBalance(string currencyCode)
to get the raw total balance (currently held by the Stable Pool and available for direct withdrawal) of the desired withdrawal currency.- If the returned balance >= withdrawal amount, user calls
bool RariFundManager.withdraw(string currencyCode, uint256 amount)
- If returned balance < withdrawal amount:
- Until the whole withdrawal amount (including the directly withdrawable balance returned above) is filled, try to withdraw and exchange each of the other currencies held by the Stable Pool (DAI, USDC, USDT, TUSD, BUSD, sUSD, and mUSD) to the desired output currency:
- User calls
uint256 RariFundManager.getRawFundBalance(string currencyCode)
to get the raw total balance held by the Stable Pool of the potential input currency in question. - Get exchange data from mStable (preferably) and/or 0x:
- If output currency is DAI, USDC, USDT, TUSD, or mUSD, get exchange data via mStable:
- If input currency is DAI, USDC, USDT, or TUSD, check
(bool, string, uint256, uint256) MassetValidationHelper(0xabcc93c3be238884cc3309c19afd128fafc16911).getMaxSwap(0xe2f2a5c287993345a840db3b0845fbc70f5935a5, address _input, address _output)
. If the first returned value istrue
, the user can exchange a maximum input amount of the third returned value. - If input currency is mUSD, check
(bool, string, uint256 output, uint256 bassetQuantityArg) MassetValidationHelper(0xabcc93c3be238884cc3309c19afd128fafc16911).getRedeemValidity(0xabcc93c3be238884cc3309c19afd128fafc16911, uint256 _mAssetQuantity, address _outputBasset)
. If the first returned value istrue
, the user can exchange a maximum input amount ofbassetQuantityArg
(the fourth returned value).
- If input currency is DAI, USDC, USDT, or TUSD, check
- If exchange via mStable is not possible (or if the user wants to exchange additional funds via 0x if mStable cannot exchange it all), retrieve order data from 0x:
- If the raw total balance of this input currency is enough to cover the remaining withdrawal amount, user retrieves data from the 0x swap quote API (see documentation (opens new window) and endpoint (opens new window)) where:
sellToken
is the input currency to be directly withdrawn from the Stable PoolbuyToken
is the output currency to be sent to the userbuyAmount
is the amount of output currency to be sent to the user in this exchange only
- If the raw total balance of this input currency is enough to cover the remaining withdrawal amount, user retrieves data from the 0x swap quote API (see documentation (opens new window) and endpoint (opens new window)) where:
- If output currency is DAI, USDC, USDT, TUSD, or mUSD, get exchange data via mStable:
- User calls
- User calls
bool RariFundProxy.withdrawAndExchange(string[] inputCurrencyCodes, uint256[] inputAmounts, address outputErc20Contract, LibOrder.Order[][] orders, bytes[][] signatures, uint256[] makerAssetFillAmounts, uint256[] protocolFees)
where:- inputCurrencyCodes is an array of input currency codes
- To directly withdraw the output currency without exchange in the same transaction, simply include the output currency code in
inputCurrencyCodes
.
- To directly withdraw the output currency without exchange in the same transaction, simply include the output currency code in
inputAmounts
is an array of input currency amounts- To directly withdraw as much of the output currency without exchange in the same transaction, set the corresponding
inputAmounts
item to the directly withdrawable raw total balance of that currency.
- To directly withdraw as much of the output currency without exchange in the same transaction, set the corresponding
outputErc20Contract
is the ERC20 token contract address of the output currency to be sent to the userorders
is an array of orders arrays returned by the 0x API- To exchange one of
inputCurrencyCodes
via mStable or to directly withdraw the output currency in the same transaction, set the correspondingorders
item to an empty array.
- To exchange one of
signatures
is an array of arrays of signatures from the orders array returned by the 0x API- To exchange one of
inputCurrencyCodes
via mStable or to directly withdraw the output currency in the same transaction, set the correspondingsignatures
item to an empty array.
- To exchange one of
makerAssetFillAmounts
is an array of output currency amounts to be sent to the user- To exchange one of
inputCurrencyCodes
via mStable or to directly withdraw the output currency in the same transaction, set the correspondingmakerAssetFillAmounts
item to 0.
- To exchange one of
protocolFees
is an array of protocol fee amounts in ETH wei to be sent to 0x- To exchange one of
inputCurrencyCodes
via mStable instead of 0x or to directly withdraw the output currency in the same transaction, set the correspondingprotocolFees
item to 0.
- To exchange one of
- inputCurrencyCodes is an array of input currency codes
- Until the whole withdrawal amount (including the directly withdrawable balance returned above) is filled, try to withdraw and exchange each of the other currencies held by the Stable Pool (DAI, USDC, USDT, TUSD, BUSD, sUSD, and mUSD) to the desired output currency:
- If the returned balance >= withdrawal amount, user calls
# RSPT (Rari Stable Pool Token)
# Introduction
Your RSPT (Rari Stable Pool Token) balance is a token-based representation of your Rari Stable Pool balance.
- RSPT is minted to you when you deposit to the Stable Pool and redeemed (i.e., burned) when you withdraw from the Stable Pool.
- Accrued interest is constantly added to your USD balance supplied to the Stable Pool, meaning the USD value of your RSPT increases. However, your RSPT balance itself does not increase: instead, the exchange rate of RSPT increases at the same rate for every user as they accrue interest.
- When you transfer your RSPT, you transfer your holdings supplied to the Stable Pool (deposits + interest).
# Usage
- Get RSPT exchange rate: Divide
RariFundManager.getFundBalance()
byRariFundToken.totalSupply()
to get the exchange rate of RSPT in USD (scaled by 1e18). - Get my RSPT balance (internal representation of my USD balance supplied):
uint256 RariFundToken.balanceOf(address account)
returns the amount of RSPT owned byaccount
. - Transfer RSPT:
bool RariFundToken.transfer(address recipient, uint256 amount)
transfersamount
RSPT torecipient
(as with other ERC20 tokens like RSPT). - Approve RSPT:
bool RariFundToken.approve(address spender, uint256 amount)
approvesspender
to spend the specifiedamount
of RSPT on behalf ofmsg.sender
- As with the
approve
functions of other ERC20 contracts, beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
- As with the
- See EIP-20: ERC-20 Token Standard (opens new window) for reference on all common functions of ERC20 tokens like RSPT.
# Total Supply & Interest
- Get total USD supplied (by all users):
uint256 RariFundManager.getFundBalance()
returns the total balance supplied by users to the Rari Stable Pool (all RSPT holders' funds but not unclaimed fees) in USD (scaled by 1e18). - Get total interest accrued (by all users):
int256 RariFundManager.getInterestAccrued()
returns the total amount of interest accrued (excluding the fees paid on interest) by past and current Rari Stable Pool users (i.e., RSPT holders) in USD (scaled by 1e18).
# Fees
See this Notion article (opens new window) for the latest fee-related information.
Performance Fees
- This fee is liable to change in the future, but the following method returns its current value at any time.
- Get interest fee rate:
uint256 RariFundManager.getInterestFeeRate()
returns the fee rate on interest (proportion of raw interest accrued scaled by 1e18).
Withdrawal Fees
- This fee is liable to change in the future, but the following method returns its current value at any time.
- Get withdrawal fee rate:
uint256 RariFundManager.getWithdrawalFeeRate()
returns the withdrawal fee rate (proportion of every withdrawal taken as a service fee scaled by 1e18).
# Raw Allocations
- Get raw currency/subpool allocations (including unclaimed fees on interest) and prices:
(string[], uint256[], RariFundController.LiquidityPool[][], uint256[][], uint256[]) RariFundProxy.getRawFundBalancesAndPrices()
returns an array of currency codes, an array of corresponding fund controller contract balances for each currency code, an array of arrays of pool indexes for each currency code, an array of arrays of corresponding balances at each pool index for each currency code, and an array of prices in USD (scaled by 1e18) for each currency code.
# Internal Stablecoin Pricing
- Get stablecoin prices (used internally by contracts):
uint256[] RariFundPriceConsumer.getCurrencyPricesInUsd()
returns an array of prices in USD (scaled by 1e18) for all supported stablecoins to which funds can be allocated (DAI, USDC, USDT, TUSD, BUSD, sUSD, and mUSD, in that order).- Use these prices to calculate the value added to a user's USD balance due to a direct deposit and the value subtracted from a user's USD balance due to a direct withdrawal.
# API
# User Balance and Interest
uint256 RariFundManager.balanceOf(address account)
Returns the total balance in USD (scaled by 1e18) supplied to the Rari Stable Pool by account
.
- Parameters:
account
(address) - The account whose balance we are calculating.
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetRawFundBalance
) potentially modifies the state.
- Ideally, we can add the
# Deposits
bool RariFundManager.isCurrencyAccepted(string currencyCode)
Returns a boolean indicating if deposits in currencyCode
are currently accepted.
- Parameters:
currencyCode
(string): The currency code to check.
string[] RariFundManager.getAcceptedCurrencies()
Returns an array of currency codes currently accepted for deposits.
RariFundProxy.deposit(string currencyCode, uint256 amount)
For the time being, we are no longer subsidizing gas fees.
Deposits funds to the Rari Stable Pool in exchange for RSPT (with GSN support).
- You may only deposit currencies accepted by the fund (see
RariFundManager.isCurrencyAccepted(string currencyCode)
). - Please note that you must approve RariFundProxy to transfer at least
amount
. - Parameters:
currencyCode
(string): The currency code of the token to be deposited.amount
(uint256): The amount of tokens to be deposited.
RariFundManager.deposit(string currencyCode, uint256 amount)
Deposits funds to the Rari Stable Pool in exchange for RSPT.
- You may only deposit currencies accepted by the fund (see
RariFundManager.isCurrencyAccepted(string currencyCode)
). However,RariFundProxy.exchangeAndDeposit
exchanges your funds via 0x and deposits them in one transaction. - Please note that you must approve RariFundManager to transfer at least
amount
. - Parameters:
currencyCode
(string): The currency code of the token to be deposited.amount
(uint256): The amount of tokens to be deposited.
RariFundProxy.exchangeAndDeposit(address inputErc20Contract, uint256 inputAmount, string outputCurrencyCode, LibOrder.Order[] orders, bytes[] signatures, uint256 takerAssetFillAmount)
Exchanges and deposits funds to the Rari Stable Pool in exchange for RSPT (via 0x).
- You can retrieve order data from the 0x swap API (opens new window). See the Contract Usage section above, the SDK, or the web client for implementation.
- Please note that you must approve RariFundProxy to transfer at least
inputAmount
unless you are inputting ETH. - You also must input at least enough ETH to cover the protocol fee (and enough to cover
orders
if you are inputting ETH). - Parameters:
inputErc20Contract
(address): The ERC20 contract address of the token to be exchanged. Set to address(0) to input ETH.inputAmount
(uint256): The amount of tokens to be exchanged (including taker fees).outputCurrencyCode
(string): The currency code of the token to be deposited after exchange.orders
(LibOrder.Order[]): The limit orders to be filled in ascending order of the price you pay.signatures
(bytes[]): The signatures for the orders.takerAssetFillAmount
(uint256): The amount of the taker asset to sell (excluding taker fees).
- Development notes:
- We should be able to make this function external and use calldata for all parameters, but Solidity does not support calldata structs (opens new window).
RariFundProxy.exchangeAndDeposit(string inputCurrencyCode, uint256 inputAmount, string outputCurrencyCode)
Exchanges and deposits funds to the Rari Stable Pool in exchange for RSPT (no slippage and low fees via mStable, but only supports DAI, USDC, USDT, TUSD, and mUSD).
- Please note that you must approve RariFundProxy to transfer at least
inputAmount
. - Parameters:
inputCurrencyCode
(string): The currency code of the token to be exchanged.inputAmount
(uint256): The amount of tokens to be exchanged (including taker fees).outputCurrencyCode
(string): The currency code of the token to be deposited after exchange.
# Withdrawals
RariFundManager.withdraw(string currencyCode, uint256 amount)
Withdraws funds from the Rari Stable Pool in exchange for RSPT.
- You may only withdraw currencies held by the fund (see
RariFundManager.getRawFundBalance(string currencyCode)
). However,RariFundProxy.withdrawAndExchange
withdraws your funds and exchanges them via 0x in one transaction. - Please note that you must approve RariFundManager to burn of the necessary amount of RSPT.
- Parameters:
currencyCode
(string): The currency code of the token to be withdrawn.amount
(uint256): The amount of tokens to be withdrawn.
RariFundProxy.withdrawAndExchange(string[] inputCurrencyCodes, uint256[] inputAmounts, address outputErc20Contract, LibOrder.Order[][] orders, bytes[][] signatures, uint256[] makerAssetFillAmounts, uint256[] protocolFees)
Withdraws funds from the Rari Stable Pool in exchange for RSPT and exchanges to them to the desired currency (if no 0x orders are supplied, exchanges DAI, USDC, USDT, TUSD, and mUSD via mStable).
- You can retrieve order data from the 0x swap API (opens new window). See the Contract Usage section above, the SDK, or the web client for implementation.
- Please note that you must approve RariFundManager to burn of the necessary amount of RSPT. You also must input at least enough ETH to cover the protocol fees.
- Parameters:
inputCurrencyCodes
(string[]): The currency codes of the tokens to be withdrawn and exchanged.- To directly withdraw the output currency without exchange in the same transaction, simply include the output currency code in
inputCurrencyCodes
.
- To directly withdraw the output currency without exchange in the same transaction, simply include the output currency code in
inputAmounts
(uint256[]): The amounts of tokens to be withdrawn and exchanged (including taker fees).- To directly withdraw as much of the output currency without exchange in the same transaction, set the corresponding
inputAmounts
item to the directly withdrawable raw fund balance of that currency.
- To directly withdraw as much of the output currency without exchange in the same transaction, set the corresponding
outputErc20Contract
(address): The ERC20 contract address of the token to be outputted by the exchange. Set to address(0) to output ETH.orders
(LibOrder.Order[][]): The 0x limit orders to be filled in ascending order of the price you pay.- To exchange one of
inputCurrencyCodes
via mStable or to directly withdraw the output currency in the same transaction, set the correspondingorders
item to an empty array.
- To exchange one of
signatures
(bytes[][]): The signatures for the 0x orders.- To exchange one of
inputCurrencyCodes
via mStable or to directly withdraw the output currency in the same transaction, set the correspondingsignatures
item to an empty array.
- To exchange one of
makerAssetFillAmounts
(uint256[]): The amounts of the maker assets to buy.- To exchange one of
inputCurrencyCodes
via mStable or to directly withdraw the output currency in the same transaction, set the correspondingmakerAssetFillAmounts
item to 0.
- To exchange one of
protocolFees
(uint256[]): The protocol fees to pay to 0x in ETH for each order.- To exchange one of
inputCurrencyCodes
via mStable instead of 0x or to directly withdraw the output currency in the same transaction, set the correspondingprotocolFees
item to 0.
- To exchange one of
- Development notes:
- We should be able to make this function external and use calldata for all parameters, but Solidity does not support calldata structs (opens new window).
# RSPT
See EIP-20: ERC-20 Token Standard (opens new window) for reference on all common functions of ERC20 tokens like RSPT. Here are a few of the most common ones:
uint256 RariFundToken.balanceOf(address account)
Returns the amount of RSPT owned by account
.
- A user's RSPT balance is an internal representation of their USD balance.
- While a user's USD balance is constantly increasing as the Rari Stable Pool accrues interest, a user's RSPT balance does not change except on deposit, withdrawal, and transfer.
- The price of RSPT is equivalent to the current value of the first $1 USD deposited to the Rari Stable Pool.
- Parameters:
account
(address) - The account whose balance we are retrieving.
bool RariFundToken.transfer(address recipient, uint256 amount)
Transfers the specified amount
of RSPT to recipient
.
- Parameters:
recipient
(address): The recipient of the RSPT.inputAmounts
(uint256[]): The amounts of tokens to be withdrawn and exchanged (including taker fees).
RETURN
value: Boolean indicating success.
bool RariFundToken.approve(address spender, uint256 amount)
Approve sender
to spend the specified amount
of RSPT on behalf of msg.sender
.
- As with the
approve
functions of other ERC20 contracts, beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - Parameters:
spender
(address) - The account to which we are setting an allowance.amount
(uint256) - The amount of the allowance to be set.
RETURN
value: Boolean indicating success.
uint256 RariFundToken.totalSupply()
Returns the total supply of RSPT (scaled by 1e18).
- Divide
RariFundManager.getFundBalance()
byRariFundToken.totalSupply()
to get the exchange rate of RSPT in USD (scaled by 1e18).
# Total Supply and Interest
uint256 RariFundManager.getFundBalance()
Returns the total balance supplied by users to the Rari Stable Pool (all RSPT holders' funds but not unclaimed fees) in USD (scaled by 1e18).
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetRawFundBalance
) potentially modifies the state.
- Ideally, we can add the
int256 RariFundManager.getInterestAccrued()
Returns the total amount of interest accrued (excluding the fees paid on interest) by past and current Rari Stable Pool users (i.e., RSPT holders) in USD (scaled by 1e18).
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetRawFundBalance
) potentially modifies the state.
- Ideally, we can add the
# Fees
uint256 RariFundManager.getInterestFeeRate()
Returns the fee rate on interest (proportion of raw interest accrued scaled by 1e18).
int256 RariFundManager.getInterestFeesGenerated()
Returns the amount of interest fees accrued by beneficiaries in USD (scaled by 1e18).
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetRawFundBalance
) potentially modifies the state.
- Ideally, we can add the
uint256 RariFundManager.getWithdrawalFeeRate()
Returns the withdrawal fee rate (proportion of every withdrawal taken as a service fee scaled by 1e18).
# Raw Total Supply, Allocations, and Interest
uint256 RariFundManager.getRawFundBalance()
Returns the raw total balance of the Rari Stable Pool (all RSPT holders' funds + all unclaimed fees) of all currencies in USD (scaled by 1e18).
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetRawFundBalance
) potentially modifies the state.
- Ideally, we can add the
uint256 RariFundManager.getRawFundBalance(string currencyCode)
Returns the raw total balance of the Rari Stable Pool (all RSPT holders' funds + all unclaimed fees) of the specified currency.
- Parameters:
currencyCode
(string): The currency code of the balance to be calculated.
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called byRariFundController.getPoolBalance
) potentially modifies the state.
- Ideally, we can add the
(string[], uint256[], RariFundController.LiquidityPool[][], uint256[][], uint256[]) RariFundProxy.getRawFundBalancesAndPrices()
Returns the fund controller's contract balance of each currency, balance of each pool of each currency (checking _poolsWithFunds
first to save gas), and price of each currency.
RETURN
values: An array of currency codes, an array of corresponding fund controller contract balances for each currency code, an array of arrays of pool indexes for each currency code, an array of arrays of corresponding balances at each pool index for each currency code, and an array of prices in USD (scaled by 1e18) for each currency code.- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetPoolBalance
) potentially modifies the state.
- Ideally, we can add the
int256 RariFundManager.getRawInterestAccrued()
Returns the raw total amount of interest accrued by the Rari Stable Pool (including the fees paid on interest) in USD (scaled by 1e18).
- Development notes:
- Ideally, we can add the
view
modifier, but Compound'sgetUnderlyingBalance
function (called bygetRawFundBalance
) potentially modifies the state.
- Ideally, we can add the
# Internal Stablecoin Pricing
uint256[] RariFundPriceConsumer.getCurrencyPricesInUsd()
Returns the prices of all supported stablecoins to which funds can be allocated.
- Use these prices to calculate the value added to a user's USD balance due to a direct deposit and the value subtracted from a user's USD balance due to a direct withdrawal.
RETURN
value: An array of prices in USD (scaled by 1e18) corresponding to the following list of currencies in the following order: DAI, USDC, USDT, TUSD, BUSD, sUSD, and mUSD.