đ§LP Stop Loss
Smart contract for Liquidity Providers on Agoric AMM
Limited Developer Support
All assets represented in this library are community built, which means limited support from the Agoric OpCo development team. Please use components, APIs, and front-ends with caution.
Summary
This contract allows a liquidity provider to the AMM to define a specific price (ratio of supplied assets) at which they would like liquidity removed. This functions as a stop-loss contract which would allow LPs to define liquidity ranges.
Details
After providing liquidity to a AMM liquidity pool and receiving in return the corresponding amount of LP tokens, the liquidity provider can instantiate a stopLoss contract that will allow him to lock the respective amount of LP tokens and specify the boundaries for a price range.
When the price of the respective AMM pool hits one of the boundaries (upper or lower), it will trigger the removal of the user assets (central and secondary tokens) from the AMM pool, in exchange for his LP tokens. Then he will be able to withdraw his assets from this contract to his purse.
At any moment the user is allowed to withdraw his locked LP tokens, remove liquidity from the AMM pool and update the price range boundaries.
When updating the boundaries, if the user specifies a range outside of the current AMM pool price, it will trigger the removal of the assets from the AMM pool.
Dependencies
There are some previous considerations to have before instantiating this contract.
The first one is related to the agoric-sdk version used at the moment of its development. The tag returned by running the command git describe --tags --always is agoricxnet-7-914-gfedf04943, so it is advised to checkout to the same state when exploring this component and test if any major update is required in order to be implemented at the desired agoric-sdk version.
When the contract is instantiated, the terms should specify the AMM publicFacet, the secondary issuer, the LP token issuer, the central issuer, and the initial boundaries.
The issuerKeywordRecord should also be specified with Central, Secondary and LpToken, being each one related to his corresponding issuer.
The third consideration regards one of the contract terms, the ammPublicFacet.
For a production environment, the ammPublicFacet should be the respective public facet of a deployed AMM instance on Zoe that the user provided liquidity to.
In a development environment, as a support for your unit tests, you can either create an instance of the AMM contract @agoric/inter-protocol/src/vpool-xyk-amm/multipoolMarketMaker.js and add the initial liquidity to the pool or you can use Agoric priceAuthority to generate the desired price quotes.
Contract Facets
The stopLoss contract exports two remotable objects, publicFacet and creatorFacet.
The publicFacet has a single method that allows any user with access to a reference of the stopLoss publicFacet to monitor the balance of the assets held by the contract.
The creator facet has multiple methods that are accessible exclusively to the contract owner, which allows him to take advantage of the features implemented by the contract such as implementing a stop-loss condition on a liquidity staking, withdrawing the locked assets and updating the price boundaries.
For each method mentioned, a more detailed description will be provided in the next section
Functionality
getBalanceByBrand
When requesting a balance of an asset held by the stopLossSeat, the caller must specify the asset keyword and issuer, which will depend on the terms and IssuerKeywords defined when the contract was instantiated.
makeUpdateConfigurationInvitation
The contract owner can update the previously defined boundaries by exercising the invitation returned by makeUpdateConfigurationInvitation().
Before implementing the new update, the contract will verify that some conditions are not violated, such as the current allocation phase is set to ACTIVE or SCHEDULED and the offerArgs has the new boundaries object.
The invitation offer needs to include the new lower and upper boundaries in the offerArgs as a price ratio. Note that if the creator specifies a range outside of the current AMM pool price, it will trigger the removal of the assets from the pool.
After the offer result promise is resolved, the price boundaries will be updated, the allocation phase will be set to active and it will return a message confirming the success of the operation.
makeLockLPTokensInvitation
After the contract owner provides liquidity to a pool and receives its LP tokens in exchange, he can lock them on the contract by exercising the invitation returned by makeLockLPTokensInvitation().
After reallocating the assets to the contract seat, the allocation phase will be updated to active.
The offer proposal has to specify the LpToken as a keyword identifier and the amount of tokens to be locked, as well as provide the respective payment. After the offer result promise is resolved, it will return a message declaring the amount of tokens locked on the contract.
makeWithdrawLpTokensInvitation
If at any moment the contract owner wishes to withdraw their locked LP tokens from the stopLoss contract to his seat, he can do it by exercising the invitation returned by makeWithdrawLpTokensInvitation().
When called, the current allocation phase needs to be active or error, being after updated to withdrawn.
When exercising this invitation, the offer proposal has to specify the LpToken as a keyword identifier. Since the owner will not give anything in this operation, there is no need for a payment.
After the offer result promise is resolved, it will return a message declaring that the tokens were withdrawn to the creator seat.
makeWithdrawLiquidityInvitation
There are two scenarios where the owner would want to call this method to withdraw his assets to his seat.
The first scenario is when the AMM pool price quote went out of the defined boundaries, and the owner assets were removed in exchange for the LP tokens.
The second scenario is when the contract owner decides to remove his liquidity from the AMM pool before the price quote of the AMM pool goes outside of any boundary.
When exercising this invitation, the offer proposal has to specify the keywords identifiers of the assets expected to receive, being Central and Secondary.
After the offer result promise is resolved, the stopLoss contract will no longer hold any asset, and the contract owner will lose his LP tokens in exchange for the asked Central and Secondary tokens. It will return as well a message declaring that the assets were withdrawn to the creator seat.
Notifiers
The stopLoss contract creates a notifierKit that keeps track of the current allocation phase, balances and boundaries. The contract owner has access to the notifier state through the exposed method on the creatorFacet.
Usage and Integration
A step-by-step guide on how the contract can be used in practice, and dependencies that must be installed can be found in the README file in the project repository. There you will find 5 different scenarios that are executed with the help of pre-built scripts that can be updated according to your preferences.
The list of unit tests built on test-stopLoss.js is also a good way to understand how to interact with the different features implemented on the stopLoss contract.
Explore on Github
https://github.com/Jorge-Lopes/stop-loss-amm
Built by Jorge Lopes
Last updated