A popular way for cryptocurrency investors to earn yield on their holdings is to deposit them in staking pools. The yield can be maximized by reinvesting the earnings, i.e. by compound interest. Traditionally, the users need to manually compound the rewards, which is time- and cost-consuming. This project provides a modular framework solution for how the interest can be automatically compounded for staking pools on Algorand network through the use of smart contracts. Specifically, it demonstrates the autocompounding ability for distribution pools (i.e. pools where the users are rewarded for staking an asset with the rewards paid in the same asset) and liquidity farming pools (i.e. pools where the users stake a token representing a portion of liquidity in an AMM liquidity pool and are rewarded with a different token). The currently written smart contracts support staking pools of Cometa with integration of Tinyman V2 for the liquidity farming pools.
There are two variations of the autocompounding smart contract - one for autocompounding of distribution pools and another one for liquidity farming pools. Both variations have the same basic structure to provide the functionality described in more detail further on. The structure is schematically depicted in the simplified figure below.
The autocompounder operates by users depositing the staking assets to it, which then forwards them to the staking pool.
This enables the contract to jointly operate with (i.e. compound) all users' funds (which are jointly tracked in global
state TS
).
The contract keeps track of each user's contribution to that amount in local state LS
.
When users deposit the staking assets to the contract, they also have to provide an ALGO deposit to cover the fees for
at least one compounding of the stake.
The action of compounding the stake consists of claiming the rewards from the staking pool and reinvesting them back to
it.
During that action, the interest earned since the last compounding of the stake gets recorded in a sequentially numbered
box (which is later used to update individual's stake).
The fees associated with these actions (i.e. transaction fees and increase in the minimal balance requirements) are
covered by the funds that were deposited by the users at the time of staking.
This allows anyone to trigger the compounding actions (without having to cover the fees).
The compounding action can be triggered this way only according to a defined schedule.
The schedule can be configured as an arbitrary function of current time (i.e. network round), times of previous
compounding actions, and the available funds to cover future compounding actions.
In the current implementation, the schedule simply defines the time of the next compounding by dividing the time between
the last compounding action LCR
and the time of pool ending PER
in equal slots, depending on the amount of available
funds.
Since new users can join at any time (meaning they deposit also additional funds for covering the compounding fees), it
means that the schedule is dynamically adjusted to maximize the yield.
Besides the scheduled compounding actions, it is also possible to trigger instantly a compounding of the stake (which
operates the same way, just requires depositing additional funds to cover the fees).
To keep track of which users have contributed how much between two compounding actions, it is tracked for each user up
to which box LNB
has one "locally claimed" the interest that is recorded in it.
Note that a user cannot claim a box that was created prior to one's joining the pool.
This mechanism with box tracking allows that users can arbitrarily add to their stake or withdraw it (partially or in
full) at any point in time.
The only prerequisite is that before adding to the stake or withdrawing, the user claims all the boxes up to the most
recent one NB
.
If the staking or withdrawal is done during the time the pool is live, the stake gets first compounded (for which the
user has to supply additional funds to cover the fees).
Note that boxes can be "locally claimed" in batches, fees for which amounts to much less compared to the case where a
user would be individually compounding the stake.
When the staking pool ends, the users should withdraw their funds from the autocompound contract in the claiming period
CP
.
After the claiming period ends or all users have withdrawn their compounded stakes, the creator of the autocompound
contract is allowed to delete the boxes and the contract.
This gives the creator the fees that were used for the creation of the boxes and any remaining staking tokens due to
rounding errors.
This mechanism gives the contract creator an incentive to gather as many users, which would also profit them from the
more frequent compounding actions.
The only difference between the autocompound contract for distribution pools and
liquidity farming pools is that in the latter case, the reward token is first
single-sidedly added to the AMM liquidity pool (i.e. zapped) before the farming token is reinvested.
Since it might not be economically efficient (or technically feasible due to limited precision) to zap very small
amounts, there is an option to set the lower limit of rewards that are zapped (MRAAL
).
If compounding does not zap the rewards, they get accumulated and zapped on next compounding if the limit is reached.
Similarly, autocompounding of other types of staking pools can easily be integrated by simply changing the steps taken
after claiming of the rewards (i.e. by modifying the claim_stake_record
internal method).
Moreover, integration of different staking pool solutions is straightforward by adapting the stake_to_pool
,
unstake_from_pool
and claim_from_pool
internal methods to fit the particular pool requirements.
The project includes a script for a sample interaction with autocompounding smart contracts through a simple command-line interface. The script implements the state machine shown in figure below.
An example scenario of interactions with the platform through the provided interaction script has been recorded and the video excerpts documented.
To test the platform with the provided script, the following is required:
- Python (>=3.10) with libraries in requirements.txt,
which can be installed using
pip install -r requirements.txt
- One or more mnemonics stored in plain text in .txt files (with spaces as delimiters) <= This is for simplicity of testing only!
- Connection to Algorand Testnet (e.g. via Sandbox or publicly available nodes by AlgoExplorer https://node.testnet.algoexplorerapi.io)
- Test ALGO and e.g. test USDC, which can both be received at https://dispenser.testnet.aws.algodev.network/
For testing, clone the repository and run the provided script.
-
Box management optimizations: Currently, a box recording the compound interest at the time of interaction is created even when the earned interest is 0 due to the limited calculation precision. Such boxes could be omitted, freeing funds for creation of additional boxes, i.e. possibility of more compounding instances.
-
Smart contract optimization: Improve code re-usage and modularity.
-
Integration of other staking platforms and AMMs on Algorand network: e.g. Humble, Algofi and Pact.
-
Implementation of different schedule strategies: Staking pools commonly give higher returns at their starts since there are fewer users participating. In such a case, it would be beneficial to compound more frequently at the start of the pool. This simply requires the exchange of the schedule module in the contract.
-
Different ALGO reward integration: Staking pools support distribution of ALGO in addition to the rewards paid in an ASA. In the current smart contract version, the ALGO rewards are used for enabling additional compounding instead of being distributed to the users.
-
Dynamic transaction fees: Currently, transaction fees are hardcoded to meet the minimum network requirement. In case of a persistent network congestion, autocompounding could not be triggered.
-
Simplify autocompound contract setup: More parameters of autocompound contract could be fetched from connected staking and swap contracts instead of being manually entered. Currently, this is due to the limited documentation of connected contracts.
-
User-friendly interface: for a seamless user experience and secure interactions (i.e. multiple wallet integrations).
The project was developed during Algorand Greenhouse Hack #3 and submitted to Yield Autocompounder category.
The smart contracts are written in PyTEAL and are ABI compliant. The command-line interface is written in Python and uses the py-algorand-sdk.
The software is not meant for production deployment - the smart contracts have not been audited and the provided test user interface does not follow the recommended security guidelines regarding handling of mnemonics.
Author: Uroš Hudomalj - https://github.com/uhudo