Autopilot moves your money around to get you the best yield in Solana. Features include: partial distributions, ability to integrate with 12+ protocols, extremely fast money movement. But really, this is a vault standard that can be applied to many more applications.
READ THIS FIRST FOR CONTEXT: https://medium.com/accrue-finance/pioneering-solanas-eip-4626-vault-standard-74a9755fe5f0
Let’s walk through an example of an Accrue $RAY vault.
-
INIT_VAULT.
This instruction creates a new account vault_info, which stores a bunch of information like our mint (e.g. $RAY), the creator of the vault, bumps, etc. We also initialize a new “pool”, which will store all the $RAY when our users deposit their funds into the vault. We also initialize a new mint accrue_mint. We will mint this token to users whenever they deposit, which function like “shares” of the total balance (similar to $mSOL). -
INIT_PROTOCOL.
After initializing the vault, we callinit_solend
to initialize the relevant accounts for our smart contract to interact with Solend. For Solend, all we have to do is initialize a token account to hold the ctokens that they mint to our wallet. The ctoken represents our shares / percentage ownership of RAY in their RAY lending pool. Throughout this doc, we will refer to our own mint as the “atoken” and will refer to protocol-minted tokens as the “ctoken”. Once we initialize our smart contract’s ctoken account, we push the protocol to an array on our vault_info to keep track of what protocols we are currently integrated with. -
DEPOSIT.
Let’s say Alice deposits 100 RAY into Autopilot. We put these funds straight into our pool, rather than directly into a lending protocol. Users should never be able to deposit straight into a protocol (explained later). The number of atokens we mint Alice equals:DEPOSIT_AMOUNT * TOTAL_BALANCE / ATOKEN_SUPPLY
. OurTOTAL_BALANCE
all of the smart contract’s funds, which may be spread across protocols and our pool. We need to fetch our balance in all the protocols and sum them before Alice can deposit. If we had three protocols, Alice would need to submit this transaction to deposit her funds:[get_balance_protocol_a, get_balance_protocol_b, get_balance_protocol_c, deposit_pool]
.Withdrawing works the same way. However, we have instructions like
withdraw_solend
to allow users to withdraw directly from protocols. This way, we don’t need to move our smart contract’s funds into the pool every time a user wants to withdraw. We can’t also havedeposit_solend
, because then someone can deposit into solend and withdraw from a different protocol over and over again to mess up our desired distribution of funds. -
SET_DISTRIBUTION.
Ok, so now we have initialized Solend’s required accounts and have some funds in our pool. Next, we set the distribution of funds across the protocols we’re integrated with by callingset_distribution
. For example, say we want 50% of our funds in Solend and 50% in Tulip’s lending market. We would callset_distribution([0%, 50%, 50%])
. The first value (0%) represents how much of our funds we want in our pool. Only the creator of the vault (i.e. money manager) can set the distribution. -
REBALANCE.
Then, we call rebalance on each protocol we are integrated with (e.g.rebalance_solend
). This calculates how much balance we want in the protocol, based on the distribution we have set, and then moves funds into the pool or withdraws into the pool. For example, Alice has deposited 100 RAY into the pool. The vault is currently integrated with two protocols. The vault creator sets the distribution to 0% 50% 50%. When we callrebalance_solend
, the smart contract will see that we want 50 RAY in Solend, but there is currently 0 RAY in Solend, so it will deposit 50 RAY from the pool into Solend. But say the distribution is [90%, 10%, 0%]. When we callrebalance_solend
, the smart contract will see that we only want 10 RAY in Solend, so it will withdraw 40 RAY from Solend and put it into the pool (50 - 10 = 40). -
DELETE_PROTOCOL.
Let’s say that we’ve initialized 3 protocols, but a fourth protocol is now offering way better APYs than the three we are integrated with. We want to get our users the best APY, so we want to integrate with that fourth protocol. However, we cannot callget_balance
on four protocols and then do an instruction likedeposit_pool
, as we are limited by Solana’s transaction size. We can calldelete_protocol_a
to remove the protocol from vault_info and add another by usinginit_protocol_b
.