From 5b61153ed365bc5af16f509ae55364cbf954a677 Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Mon, 6 Feb 2023 14:08:26 +0100 Subject: [PATCH 1/7] fix: add svg astral logo --- whitepaper/ images/astral.svg | 19 ++ whitepaper/ALDEX_Whitepaper_VC_version.tex | 199 +++++++++++---------- 2 files changed, 127 insertions(+), 91 deletions(-) create mode 100644 whitepaper/ images/astral.svg diff --git a/whitepaper/ images/astral.svg b/whitepaper/ images/astral.svg new file mode 100644 index 0000000..543683f --- /dev/null +++ b/whitepaper/ images/astral.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/whitepaper/ALDEX_Whitepaper_VC_version.tex b/whitepaper/ALDEX_Whitepaper_VC_version.tex index 359004e..85ae7f1 100644 --- a/whitepaper/ALDEX_Whitepaper_VC_version.tex +++ b/whitepaper/ALDEX_Whitepaper_VC_version.tex @@ -8,18 +8,28 @@ % \linenumbers \usepackage{listings} \usepackage{graphicx} +\usepackage{svg} \usepackage{dirtytalk} %for quotations \graphicspath{{./images/}} \usepackage{amsmath} %for fractions \usepackage{amssymb} %for checkmark \usepackage[style=numeric,sorting=none]{biblatex} -\addbibresource{biblio.bib} +\usepackage{fetamont} +\addbibresource{./biblio.bib} \renewcommand{\arraystretch}{2} - -\title{Astral DEX Whitepaper} - -\author{Astral DEX Research Team} +\newcommand{\AstralName}[1]{\includesvg[width={#1}]{astral.svg}} +\newcommand{\AstralWS}{\AstralName{0.5in}} % Without Space after the figure +\newcommand{\Astral}{\AstralName{0.5in}~} +\newcommand{\AstralTitle}{\AstralName{0.95in}~} +\newcommand{\AstralSubtitle}{\AstralName{0.65in}~} +\newcommand{\AstralSection}{\AstralName{0.65in}~} +\newcommand{\AstralSubsection}{\AstralName{0.6in}} +\newcommand{\AstralSubsubsection}{\AstralName{0.55in}} + +\title{\AstralTitle DEX Whitepaper} + +\author{\AstralSubtitle Research Team} \date{\today} \hypersetup{pdfauthor={Name}} @@ -35,7 +45,7 @@ \maketitle \begin{abstract} -Astral DEX (Astral) is a cutting edge decentralized exchange that combines and surpasses the functionalities of current decentralized exchanges and classical centralized exchanges. The core improvements are increased capital efficiency, risk tolerance, simplicity, and flexibility, leading to much lower swap costs and better UX for users compared to other decentralized exchanges. Astral achieves these advancements through a proprietary feature combination including Concentrated Liquidity, Single Pool Contracts, Advanced Order Types, and Single Token Liquidity. The general principles of these features and the mathematical foundation underlying Astral\textsc{\char13}s mechanics are provided below. +\Astral DEX (\AstralWS) is a cutting edge decentralized exchange that combines and surpasses the functionalities of current decentralized exchanges and classical centralized exchanges. The core improvements are increased capital efficiency, risk tolerance, simplicity, and flexibility, leading to much lower swap costs and better UX for users compared to other decentralized exchanges. \Astral achieves these advancements through a proprietary feature combination including Concentrated Liquidity, Single Pool Contracts, Advanced Order Types, and Single Token Liquidity. The general principles of these features and the mathematical foundation underlying \AstralWS\textsc{\char13}s mechanics are provided below. \end{abstract} \tableofcontents \clearpage @@ -73,12 +83,12 @@ \section{List of Abbreviations} \section{Introduction} \ActivateWarningFilters[pdftoc] -\subsection{What is Astral DEX?} +\subsection{What is \AstralSubsection?} \label{whatisAstral} \DeactivateWarningFilters[pdftoc] -Astral DEX (Astral) is a cutting edge decentralized exchange (DEX)\footnote{Decentralized exchanges (DEXs) are a cornerstone of DeFi. DEXs are peer-to-peer marketplaces where transactions occur directly between crypto traders without requiring an intermediary.} that combines and improves the functionalities of existing decentralized and centralized exchanges. Astral combines advanced features, including Concentrated Liquidity (CL), Single Pool Contracts (SPC), Single Token Liquidity (STL), Advanced Order Types (AOT), and Triple-Layered Risk Protection, to create a versatile and powerful DEX which tremendously improves capital efficiency\footnote{Capital efficiency is how effectively capital is utilized to generate returns or meet production goals. For example, \$1 of capital that produces \$1 in returns is more capital efficient than \$1 that produces \$0.10 in returns if both are utilizing the same investment strategy.} and ease of use, offering users lower swap costs and a better user experience. +\Astral DEX (\AstralWS) is a cutting edge decentralized exchange (DEX)\footnote{Decentralized exchanges (DEXs) are a cornerstone of DeFi. DEXs are peer-to-peer marketplaces where transactions occur directly between crypto traders without requiring an intermediary.} that combines and improves the functionalities of existing decentralized and centralized exchanges. \Astral combines advanced features, including Concentrated Liquidity (CL), Single Pool Contracts (SPC), Single Token Liquidity (STL), Advanced Order Types (AOT), and Triple-Layered Risk Protection, to create a versatile and powerful DEX which tremendously improves capital efficiency\footnote{Capital efficiency is how effectively capital is utilized to generate returns or meet production goals. For example, \$1 of capital that produces \$1 in returns is more capital efficient than \$1 that produces \$0.10 in returns if both are utilizing the same investment strategy.} and ease of use, offering users lower swap costs and a better user experience. -For those unfamiliar with the field, this introduction will provide a broad overview of the key concepts and developments related to Astral. +For those unfamiliar with the field, this introduction will provide a broad overview of the key concepts and developments related to \AstralWS. \subsection{Rise of Cryptocurrencies and Early Decentralized Finance} \label{defi} @@ -98,14 +108,14 @@ \subsection{Decentralized Finance and Exchanges} \subsection{CFMM as the First DeFi Automated Market Maker} \label{cfmmasamm} -CFMM is the most common liquidity provision strategy of a DeFi product class known as the Automated Market Maker (AMM), a term often used interchangeably with DEX due to the vast majority of DEXs using the AMM model for liquidity provision. AMMs do not use an orderbook like a traditional exchange. Instead, in an AMM, assets are priced automatically according to a specific pricing algorithm. The exact algorithm may vary from protocol to protocol. However, the original algorithm in constant function market makers, which is still commonly used, is $x \cdot y = k$. In this formula, $x$ and $y$ are amounts of two tokens provided by the market maker, and $k$ is a fixed constant that is invariant during a swap. Recently, more complex algorithms have gained adoption, such as Concentrated Liquidity (CL)\footnote{Concentrated Liquidity is a mechanic that allows liquidity providers to add their liquidity to a specific part of the price curve to \say{concentrate} it, typically around the commonly traded price range, which leads to higher capital efficiency.}, which Astral uses as well \cite{UniswapV3Core}. +CFMM is the most common liquidity provision strategy of a DeFi product class known as the Automated Market Maker (AMM), a term often used interchangeably with DEX due to the vast majority of DEXs using the AMM model for liquidity provision. AMMs do not use an orderbook like a traditional exchange. Instead, in an AMM, assets are priced automatically according to a specific pricing algorithm. The exact algorithm may vary from protocol to protocol. However, the original algorithm in constant function market makers, which is still commonly used, is $x \cdot y = k$. In this formula, $x$ and $y$ are amounts of two tokens provided by the market maker, and $k$ is a fixed constant that is invariant during a swap. Recently, more complex algorithms have gained adoption, such as Concentrated Liquidity (CL)\footnote{Concentrated Liquidity is a mechanic that allows liquidity providers to add their liquidity to a specific part of the price curve to \say{concentrate} it, typically around the commonly traded price range, which leads to higher capital efficiency.}, which \Astral uses as well \cite{UniswapV3Core}. \subsection{Trading Pairs} \label{traidingpairs} -There are trading pairs in AMMs. These token pairs exist as liquidity pools. If a user wants to be a liquidity provider (LP), which allows earning fees through market making, the user has to add two tokens of equal value to the pool (according to the formula previously mentioned $x \cdot y = k$). After adding liquidity to the pool, the LP receives yield-bearing tokens called LP tokens, for which the amount received corresponds to the LP\textsc{\char13}s proportion of capital within the pool. These tokens then internally accrue trading fees generated as users trade with the pool. In Astral , one of the two tokens will always be vAUSD\footnote{Virtual AUSD (vAUSD) is a virtual stablecoin AUSD, which is backed by all the assets in Astral pools. It is not mintable or directly tradable, and exists only as a virtual intermediary, or unit of account, which enables Astral\textsc{\char13}s advanced feature set.}. +There are trading pairs in AMMs. These token pairs exist as liquidity pools. If a user wants to be a liquidity provider (LP), which allows earning fees through market making, the user has to add two tokens of equal value to the pool (according to the formula previously mentioned $x \cdot y = k$). After adding liquidity to the pool, the LP receives yield-bearing tokens called LP tokens, for which the amount received corresponds to the LP\textsc{\char13}s proportion of capital within the pool. These tokens then internally accrue trading fees generated as users trade with the pool. In \AstralWS, one of the two tokens will always be vAUSD\footnote{Virtual AUSD (vAUSD) is a virtual stablecoin AUSD, which is backed by all the assets in \Astral pools. It is not mintable or directly tradable, and exists only as a virtual intermediary, or unit of account, which enables \AstralWS\textsc{\char13}s advanced feature set.}. \subsection{Cryptocurrency Milestones} -To conclude this introduction, in the history of cryptocurrency, Ethereum and Bitcoin will forever remain milestone projects for providing the first decentralized currency and first Turing-complete language that could operate with a decentralized currency. Uniswap was also a landmark addition for being the first DEX to utilize an AMM. However, DeFi is still in its early years, and the DEXs on the market have many remaining problems and inefficiencies. By providing a solution to these problems, we intend to make Astral another DeFi milestone by combining the strengths of and surpassing both decentralized and centralized exchanges. +To conclude this introduction, in the history of cryptocurrency, Ethereum and Bitcoin will forever remain milestone projects for providing the first decentralized currency and first Turing-complete language that could operate with a decentralized currency. Uniswap was also a landmark addition for being the first DEX to utilize an AMM. However, DeFi is still in its early years, and the DEXs on the market have many remaining problems and inefficiencies. By providing a solution to these problems, we intend to make \Astral another DeFi milestone by combining the strengths of and surpassing both decentralized and centralized exchanges. \section{Pain Points and Problems of Current AMMs} \subsection{Pain Points of Current AMMs} @@ -124,56 +134,56 @@ \subsection{Pain Points of Current AMMs} So in any DEX swap, there is only a passive LP side and an active trader side. As a result, when compared to CEXs that have various AOTs that facilitate a multitude of strategies, DEXs are subpar in versatility and capability for traders and LPs. \ActivateWarningFilters[pdftoc] -\subsection{How Does Astral Solve the Problems of Current AMMs?} +\subsection{How Does \Astral Solve the Problems of Current AMMs?} \label{howAstralsolves} \DeactivateWarningFilters[pdftoc] \begin{itemize} - \item \textbf{Superior capital efficiency of STL, SPC and CL:} Instead of fragmenting liquidity across numerous pool pairs for each token, Astral utilizes SPC pools coupled with STL\footnote{Single Token Liquidity (STL) is a mechanic that allows liquidity providers to provide only one token to open a position. Each token is paired with vAUSD in a smart contract.} through the virtual platform token vAUSD. With STL, LPs only need to deposit one token of their choice, which is matched with the virtual stablecoin vAUSD, making the process of LPing only require half the capital of existing DEXs. With SPC, the liquidity for each token is unified, resulting in a much lower price impact. SPC and STL significantly improve capital efficiency and thus allows Astral to offer lower swap costs + \item \textbf{Superior capital efficiency of STL, SPC and CL:} Instead of fragmenting liquidity across numerous pool pairs for each token, \Astral utilizes SPC pools coupled with STL\footnote{Single Token Liquidity (STL) is a mechanic that allows liquidity providers to provide only one token to open a position. Each token is paired with vAUSD in a smart contract.} through the virtual platform token vAUSD. With STL, LPs only need to deposit one token of their choice, which is matched with the virtual stablecoin vAUSD, making the process of LPing only require half the capital of existing DEXs. With SPC, the liquidity for each token is unified, resulting in a much lower price impact. SPC and STL significantly improve capital efficiency and thus allows \Astral to offer lower swap costs - Astral also uses Concentrated Liquidity (CL), which allows for more focused liquidity distribution around active price ranges, providing far superior capital efficiency compared to AMMs using $x \cdot y = k$. As a result, CL further lowers swap costs for traders and increases the earning potential of liquidity providers. + \Astral also uses Concentrated Liquidity (CL), which allows for more focused liquidity distribution around active price ranges, providing far superior capital efficiency compared to AMMs using $x \cdot y = k$. As a result, CL further lowers swap costs for traders and increases the earning potential of liquidity providers. \item \textbf{Single-hop instead of multi-hop swaps:} Due to each STL pool taking the form of TokenA/vAUSD, transactions between any 2 tokens can happen in effectively one hop using the virtual vAUSD as an invisible intermediary. This means any swap, no matter how niche the tokens are, will incur only a single swap fee, which scales perfectly for long-tail assets and a growing cryptocurrency market (more info in section \ref{swapping}). - \item \textbf{Single Token Provision:} STL eliminates the dual-token entry barrier of traditional AMMs. Astral\textsc{\char13}s liquidity provision process is much simpler for users, allowing them to LP any single token of any amount. This aspect of STL is called Single Token Provision (STP). In the second aspect of STL, vAUSD matching, users deposit TokenA, and Astral matches it with vAUSD. This also means that new companies don\textsc{\char13}t need to have funds to pair their token with and can LP it directly for their users to trade against. (Note: Astral has a whitelist of high-cap tokens which are freely tradeable. Due to vAUSD matching, for new tokens, Astral has restrictions in place to prevent the LP of malicious tokens, and new companies will have to apply for whitelisting to take advantage of STL. Described further in section \ref{stl}). - \item \textbf{Versatile AOT:} Astral will feature AOTs (described in section \ref{aot}), such as a generalized analogue of limit orders we call Continuous Limit Orders (CLO)\footnote{A Continuous Limit Order is a limit order that is added to the liquidity of any segment. A CLO is executed only at a price/price range in one direction, which is defined by the user. For more information, see section \ref{clo}.}. In addition, Astral will incorporate at-tick liquidity\footnote{At-tick liquidity is liquidity provided at a fixed price (this price can only be at ticks). For more information, see \label{segments}}, another novel approach that creates a unique and valuable solution for the use cases of both stablecoin swaps and, coupled with CLOs, classic limit orders. These AOTs allow traders and LPs to utilize much more flexible strategies, opening up an array of financial use cases. + \item \textbf{Single Token Provision:} STL eliminates the dual-token entry barrier of traditional AMMs. \AstralWS\textsc{\char13}s liquidity provision process is much simpler for users, allowing them to LP any single token of any amount. This aspect of STL is called Single Token Provision (STP). In the second aspect of STL, vAUSD matching, users deposit TokenA, and \Astral matches it with vAUSD. This also means that new companies don\textsc{\char13}t need to have funds to pair their token with and can LP it directly for their users to trade against. (Note: \Astral has a whitelist of high-cap tokens which are freely tradeable. Due to vAUSD matching, for new tokens, \Astral has restrictions in place to prevent the LP of malicious tokens, and new companies will have to apply for whitelisting to take advantage of STL. Described further in section \ref{stl}). + \item \textbf{Versatile AOT:} \Astral will feature AOTs (described in section \ref{aot}), such as a generalized analogue of limit orders we call Continuous Limit Orders (CLO)\footnote{A Continuous Limit Order is a limit order that is added to the liquidity of any segment. A CLO is executed only at a price/price range in one direction, which is defined by the user. For more information, see section \ref{clo}.}. In addition, \Astral will incorporate at-tick liquidity\footnote{At-tick liquidity is liquidity provided at a fixed price (this price can only be at ticks). For more information, see \ref{segments}}, another novel approach that creates a unique and valuable solution for the use cases of both stablecoin swaps and, coupled with CLOs, classic limit orders. These AOTs allow traders and LPs to utilize much more flexible strategies, opening up an array of financial use cases. \end{itemize} \ActivateWarningFilters[pdftoc] -\section{Astral Features} +\section{Features} \DeactivateWarningFilters[pdftoc] -Astral is an AMM that delivers significantly improved capital efficiency, simplicity, and flexibility for LPs compared to other DEXs. Astral also provides new AOTs and other sophisticated features, offering value to traders and LPs beyond the current decentralized and centralized exchanges. +\Astral is an AMM that delivers significantly improved capital efficiency, simplicity, and flexibility for LPs compared to other DEXs. \Astral also provides new AOTs and other sophisticated features, offering value to traders and LPs beyond the current decentralized and centralized exchanges. \subsection{Concentrated Liquidity} CL was first used by Uniswap V3. In earlier versions, LPs could only provide liquidity across the entire price range\footnote{The range is a part of the price curve between two initialized ticks of a given LP position. For more information on the structure of concentrated liquidity pools, see \ref{cl_Astral}.} between 0 and infinity. In that prior implementation, most of the liquidity was never utilized because prices often move only within one part of the price curve. The main idea of CL is to allow LPs to concentrate their liquidity within a specific price range (between two price ticks\footnote{Ticks are the boundaries between discrete areas in the price curve. Each tick is $0.01\%$ (1 basis point) away from neighbouring ticks. For more information on the structure of concentrated liquidity pools, see \ref{cl_Astral}.}), with the common goal of fitting that range closely to the price range where assets see most of their trading volume, such as .99-1.01 for a stablecoin. LPs can create as many positions as they want, creating an individualized price curve. If the price moves out of the position interval, the position becomes inactive and stops earning fees. \subsubsection{Customized Fee Tiers} -CL gives LPs the option of choosing customized fee tiers for their liquidity which makes the structure of Astral\textsc{\char13}s trading markets more optimal by better fitting the demand curves of market participants. Choosing the right fee tier when providing liquidity is a complex issue; Traders want to pay lower fees, but LPs want to earn more fees from traders, which are opposing interests. Most DEXs currently have a standard fee of around 0.3\%. However, it makes sense to have a lower fee for swaps between like-kind assets such as stablecoins because the risk for LPs to provide liquidity to them is lower. Likewise, a higher fee tier such as 1\% is justified for exotic pairs such as niche tokens. This higher fee tier can compensate for the risk to LPs from the higher volatility of these tokens. +CL gives LPs the option of choosing customized fee tiers for their liquidity which makes the structure of \AstralWS\textsc{\char13}s trading markets more optimal by better fitting the demand curves of market participants. Choosing the right fee tier when providing liquidity is a complex issue; Traders want to pay lower fees, but LPs want to earn more fees from traders, which are opposing interests. Most DEXs currently have a standard fee of around 0.3\%. However, it makes sense to have a lower fee for swaps between like-kind assets such as stablecoins because the risk for LPs to provide liquidity to them is lower. Likewise, a higher fee tier such as 1\% is justified for exotic pairs such as niche tokens. This higher fee tier can compensate for the risk to LPs from the higher volatility of these tokens. Given the complexity of the topic, inexperienced users can choose to use the opt-in default settings to maximize the amount of trading fees they get. Advanced users can choose any fee tier (1\%, 0.3\%, 0.05\% or 0.01\% for any token). -All in all, CL and customized fee tiers provide a significant boost to capital efficiency and market optimization. While Astral is not the first DEX to implement CL, it is Astral\textsc{\char13}s combination of CL with other core features (like SPC) that makes Astral unique and value-generating. +All in all, CL and customized fee tiers provide a significant boost to capital efficiency and market optimization. While \Astral is not the first DEX to implement CL, it is \AstralWS\textsc{\char13}s combination of CL with other core features (like SPC) that makes \Astral unique and value-generating. \subsection{Single Pool Contracts and Single Token Liquidity} -To optimize capital efficiency and simplicity for users, Astral implemented SPC and STL. With SPC, each ERC20 token\cite{erc20} has only a single liquidity pool comprising of said token and vAUSD (virtual stablecoin AUSD). +To optimize capital efficiency and simplicity for users, \Astral implemented SPC and STL. With SPC, each ERC20 token\cite{erc20} has only a single liquidity pool comprising of said token and vAUSD (virtual stablecoin AUSD). -With STL, providing liquidity is much easier and requires less capital, as users only need to provide one token instead of two, as is commonly the case in DEXs. This lowers the entry threshold for LPs, effectively lowering the cost of participation, which should increase the Astral\textsc{\char13}s user base and liquidity. +With STL, providing liquidity is much easier and requires less capital, as users only need to provide one token instead of two, as is commonly the case in DEXs. This lowers the entry threshold for LPs, effectively lowering the cost of participation, which should increase the \AstralWS\textsc{\char13}s user base and liquidity. Another advantage of SPC is that any swap between two tokens consists of a single hop using vAUSD as an invisible, virtual intermediary ($Token1 \rightarrow vAUSD \rightarrow Token2$). This solution eliminates multi-hop transaction paths and their resulting increased swap costs (more info in section \ref{swapping}). \subsection{LPing, and Using Single Token Liquidity} -In Astral, a user can open an LP position within a specific price range (see section \ref{concentrated_liquidity}). When opening the position, the user is allowed to optionally match vAUSD to take advantage of a 2x capital efficiency improvement through Single Token Liquidity (STL). In other words, for any token provided as liquidity into Astral, an equal value of vAUSD can be matched from the protocol as additional liquidity into that position, increasing resulting yields from the user\textsc{\char13}s position. +In \AstralWS, a user can open an LP position within a specific price range (see section \ref{concentrated_liquidity}). When opening the position, the user is allowed to optionally match vAUSD to take advantage of a 2x capital efficiency improvement through Single Token Liquidity (STL). In other words, for any token provided as liquidity into \AstralWS, an equal value of vAUSD can be matched from the protocol as additional liquidity into that position, increasing resulting yields from the user\textsc{\char13}s position. \subsection{Advanced Order Types} \label{aot} -Astral has developed several Advanced Order Types to surpass the capabilities of current DEXs. These AOTs are described below. +\Astral has developed several Advanced Order Types to surpass the capabilities of current DEXs. These AOTs are described below. \subsubsection{Segments} \label{segments} -Unlike current DEXs, which distribute liquidity uniformly over a price range (true even of Uniswap V3, which utilizes sub-ranges through concentrated liquidity), Astral utilizes \say{alternating} trading Segments which possess ranges and ticks. In Astral, liquidity is held in the range between two ticks, and at the ticks. The latter, called at-tick liquidity, allows for swapping for a fixed price at a given tick, much like limit orders. +Unlike current DEXs, which distribute liquidity uniformly over a price range (true even of Uniswap V3, which utilizes sub-ranges through concentrated liquidity), \Astral utilizes \say{alternating} trading Segments which possess ranges and ticks. In \AstralWS, liquidity is held in the range between two ticks, and at the ticks. The latter, called at-tick liquidity, allows for swapping for a fixed price at a given tick, much like limit orders. -The fixed prices at ticks also allow for stablecoin-stablecoin pairs to potentially have large liquidity at exact prices such as \$1, providing a semi-strict pegging mechanism that will hold at a tick\textsc{\char13}s price as long as liquidity exists at that tick. In comparison, in current CFMM models like Uniswap V3 or Curve, asset prices, even for stablecoins, naturally swing across wider price ranges because there is no direct functionality built-in for liquidity walls to form within very narrow ranges such as at specific price ticks. Meanwhile, Astral facilitates tighter liquidity concentration. As a second order effect, this enables trading at lower fees due to decreased price impact. +The fixed prices at ticks also allow for stablecoin-stablecoin pairs to potentially have large liquidity at exact prices such as \$1, providing a semi-strict pegging mechanism that will hold at a tick\textsc{\char13}s price as long as liquidity exists at that tick. In comparison, in current CFMM models like Uniswap V3 or Curve, asset prices, even for stablecoins, naturally swing across wider price ranges because there is no direct functionality built-in for liquidity walls to form within very narrow ranges such as at specific price ticks. Meanwhile, \Astral facilitates tighter liquidity concentration. As a second order effect, this enables trading at lower fees due to decreased price impact. -In summary, Astral provides the pricing efficiency of CEXs\textsc{\char13} orderbooks, as well as the DeFi simplicity of DEXs\textsc{\char13} ranged positions, all within Astral\textsc{\char13}s decentralized on-chain format. +In summary, \Astral provides the pricing efficiency of CEXs\textsc{\char13} orderbooks, as well as the DeFi simplicity of DEXs\textsc{\char13} ranged positions, all within \AstralWS\textsc{\char13}s decentralized on-chain format. \subsubsection{Continuous Limit Orders} \label{clo} @@ -182,21 +192,21 @@ \subsubsection{Continuous Limit Orders} On the other hand, in current DEXs, if an LP wants to build a one-way position across a chosen price range, they actively need to either chain high-fee market orders or continuously add and remove liquidity as prices shift, which can only be done somewhat accurately through automation. So from a trading strategy perspective, LPs in existing DEXs have limited flexibility, with their strategies being forced to act a continuous version of grid trading\footnote{Grid trading is a strategy that involves placing buy and sell orders at set intervals around a set price. A grid can be created to profit from trend breakouts (buy orders are placed above a set price and sell orders are placed below) or range consolidations (buy orders are placed below a set price and sell orders are placed above).}. Meanwhile, CLOs are a continuous version of simple limit orders, which as a more elementary order/strategy type, can be harnessed more malleably and combined into various strategies. \subsubsection{Comparison Table} -Finally, we present a table that shows how different strategies can be performed in Astral compared to the current generation of DEXs and CEXs to illustrate Astral\textsc{\char13}s powerful advantages over both. +Finally, we present a table that shows how different strategies can be performed in \Astral compared to the current generation of DEXs and CEXs to illustrate \AstralWS\textsc{\char13}s powerful advantages over both. \begin{table}[h] -\caption{Comparison of different trading strategies and their implementations in Astral and other exchanges} +\caption{Comparison of different trading strategies and their implementations in \Astral and other exchanges} \label{table:trading_types} \vskip 0.5cm \centering \begin{tabular}{p{0.1\textwidth}p{0.25\textwidth}p{0.15\textwidth}p{0.2\textwidth}p{0.15\textwidth}} \hline \hline - Order Type & User Purpose & CEXs & DEXs & Astral \\ + Order Type & User Purpose & CEXs & DEXs & \Astral \\ \hline Active & Ready to cross the spread or pay commissions; unwilling to wait & Market Order, discrete only & Swap & Swap\\ - + Passive & Wants to passively buy or sell with minimal commission; willing to wait & Limit Orders, discrete only & Mostly N/A & Continous limit orders$^a$, discrete$^a$ and continuous$^c$\\ - + Market Maker & Wants to get commissions and/or spread & Grid Trading, discrete only & CFMM Liquidity, continuous & CFMM Liquidity$^b$, continuous$^b$ and discrete$^a$ \\ \hline \end{tabular} @@ -207,38 +217,38 @@ \subsubsection{Comparison Table} \section{Capital Efficiency And Flexibility Gains} \subsection{Importance of Capital Efficiency} -The main improvement of Uniswap V3 that enabled it to become the leading decentralized exchange was increased capital efficiency. On Uniswap V3, LPs can better concentrate their liquidity and earn higher fees as a result. This innovation has lowered the cost of swapping by lowering price impact costs, making Uniswap V3\textsc{\char13}s generalized DEX competitive with specialized stablecoin DEXs and CEXs. Astral\textsc{\char13}s innovations are a further advancement in that same direction. Astral provides additional capital efficiency, along with improved flexibility in capital allocation. +The main improvement of Uniswap V3 that enabled it to become the leading decentralized exchange was increased capital efficiency. On Uniswap V3, LPs can better concentrate their liquidity and earn higher fees as a result. This innovation has lowered the cost of swapping by lowering price impact costs, making Uniswap V3\textsc{\char13}s generalized DEX competitive with specialized stablecoin DEXs and CEXs. \AstralWS\textsc{\char13}s innovations are a further advancement in that same direction. \Astral provides additional capital efficiency, along with improved flexibility in capital allocation. \subsection{Capital Efficiency Benchmark} We use Uniswap V1 as the basic benchmark for our capital efficiency analyses because it was the first AMM\footnote{Perhaps analysts will consider other benchmarks in the future, but the reference of Uniswap V1 may still be relevant years from now, like how we still use the horsepower benchmark in the automotive industry even after a hundred years.}. Hence, capital efficiency gains described in this whitepaper can be assumed to be a multiplier of Uniswap V1 unless stated otherwise. \textit{Note: there was no capital efficiency improvement between Uniswap V1 and V2. So for the sake of capital efficiency comparisons, they are interchangeable, and we will use Uniswap V1.} \ActivateWarningFilters[pdftoc] -\subsection{ Superior Capital Efficiency of Astral} +\subsection{ Superior Capital Efficiency of \Astral} \DeactivateWarningFilters[pdftoc] \label{superior-ce} -Astral has significantly improved capital efficiency over Uniswap V3, which already had substantial gains over Uniswap V1/V2 and is seen as the most capital efficient DEX among varied assets today. The Uniswap team claims that with a price range of 0.1\%, the efficiency can reach 4000x \cite{UniswapIntro}. It is mentioned that it can reach 20,000x with a minimum price range of 0.02\%. +\Astral has significantly improved capital efficiency over Uniswap V3, which already had substantial gains over Uniswap V1/V2 and is seen as the most capital efficient DEX among varied assets today. The Uniswap team claims that with a price range of 0.1\%, the efficiency can reach 4000x \cite{UniswapIntro}. It is mentioned that it can reach 20,000x with a minimum price range of 0.02\%. Technically, the Uniswap V3 implementation allows a price range of 0.01\%, so the maximum gain is 40,000x. However, this is at theoretical limit; In typical uses cases, it\textsc{\char13}s closer to a 40x-100x improvement. -As for Astral, the capital efficiency enhancement Astral provides compared to Uniswap V3 is a further 10-20x\footnote{This is relative to Uniswap V3. So if Astral provided a 10x improvement over Uniswap V3, that would be a 40,000x improvement over Uniswap V1 with a 0.1\% price range, whereas Uniswap V3 has 4000x.} for typical use cases. Advanced users can get further capital efficiency improvements through STL and Advanced Order Types, up to a realistic theoretical upper bound of 20,000,000x compared to Uniswap V1 (more info in section \ref{future_gains}). This equates to a 500x improvement over Uniswap V3. +As for \AstralWS, the capital efficiency enhancement \Astral provides compared to Uniswap V3 is a further 10-20x\footnote{This is relative to Uniswap V3. So if \Astral provided a 10x improvement over Uniswap V3, that would be a 40,000x improvement over Uniswap V1 with a 0.1\% price range, whereas Uniswap V3 has 4000x.} for typical use cases. Advanced users can get further capital efficiency improvements through STL and Advanced Order Types, up to a realistic theoretical upper bound of 20,000,000x compared to Uniswap V1 (more info in section \ref{future_gains}). This equates to a 500x improvement over Uniswap V3. These improvements can also scale as the cryptocurrency market grows, gaining an additional 10x multiplier as more tokens trade on the market, up to 100x if all traditional equities, such as stocks, develop cryptocurrency equivalents. This would reach a theoretical upper bound to 40,000,000x of Uniswap V1. -Capital efficiency gains in Astral come from CL, SPC, and STL. In addition, in some cases, such as stablecoins and certain special situations, LPs and CLOs can provide additional capital efficiency boosts. While CL gains are similar to Uniswap V3 gains, the other components of Astral add completely independent multipliers. In fact, even within the CL component, Astral will provide additional capital efficiency through at-tick Segments and CLOs. +Capital efficiency gains in \Astral come from CL, SPC, and STL. In addition, in some cases, such as stablecoins and certain special situations, LPs and CLOs can provide additional capital efficiency boosts. While CL gains are similar to Uniswap V3 gains, the other components of \Astral add completely independent multipliers. In fact, even within the CL component, \Astral will provide additional capital efficiency through at-tick Segments and CLOs. The maximum and typical quantified gains that a user receives are discussed below. \subsubsection{Regular Users} -For typical use cases, the capital efficiency gains of Astral will be about 400x due to 3 factors: +For typical use cases, the capital efficiency gains of \Astral will be about 400x due to 3 factors: \begin{enumerate} \item CL within a range of $\pm 5\%$ (10\% range) improves capital efficiency by 40x: - + In Uniswap V1, if a token\textsc{\char13}s price moves 5\%, the number of tokens will increase by $\sim 2.5\%$ on one side and decrease by $\sim 2.5\%$ on the other side, so only 2.5\% of tokens will be bought/sold compared to 100\% for CL. \item SPC improves efficiency by 5x: - Instead of LPing TokenA into numerous fragmented paired pools, LPs in Astral add liquidity for TokenA into a unified pool, which participates in all of Astral\textsc{\char13}s corresponding swaps for TokenA. In current markets, this improves efficiency by about 5x for the LP. + Instead of LPing TokenA into numerous fragmented paired pools, LPs in \Astral add liquidity for TokenA into a unified pool, which participates in all of \AstralWS\textsc{\char13}s corresponding swaps for TokenA. In current markets, this improves efficiency by about 5x for the LP. It\textsc{\char13}s worth noting that as the scale of DeFi and trading on DEXs grows, as more pairs are created, and the long tail of available assets to trade against increases, this improvement of SPC will scale up considerably from 5x. \item STL improves efficiency by 2x: @@ -257,9 +267,9 @@ \subsubsection{Advanced Users} \subsubsection{Future Gains and Realistic Upper Bound} \label{future_gains} -Mathematically, there is no upper bound on the capital efficiency that Astral will provide because the SPC multiplier of capital efficiency has no upper bound. However, some realistic upper bound needs to be outlined. In addition, the other part that provides a potentially infinite increase in liquidity is at-tick liquidity, which can give a much stronger pegging for stablecoins. +Mathematically, there is no upper bound on the capital efficiency that \Astral will provide because the SPC multiplier of capital efficiency has no upper bound. However, some realistic upper bound needs to be outlined. In addition, the other part that provides a potentially infinite increase in liquidity is at-tick liquidity, which can give a much stronger pegging for stablecoins. -As the number of cryptocurrencies increases, the 5-10x gain in SPC could roughly equal the number of tokens actively traded. So, if traditional equity markets move to the blockchain at some point, this gain could theoretically become 1000-2000x. As technology advances, higher STL levels close to 4-5x may also be developed in Astral. Thus, the three multipliers for these components will yield the below capital efficiency improvement for Advanced Users: +As the number of cryptocurrencies increases, the 5-10x gain in SPC could roughly equal the number of tokens actively traded. So, if traditional equity markets move to the blockchain at some point, this gain could theoretically become 1000-2000x. As technology advances, higher STL levels close to 4-5x may also be developed in \AstralWS. Thus, the three multipliers for these components will yield the below capital efficiency improvement for Advanced Users: \begin{center} $4,000(CL)\cdot1,000(SPC)\cdot5(STL)=20,000,000x$ @@ -267,7 +277,7 @@ \subsubsection{Future Gains and Realistic Upper Bound} \subsection{Detailed Tables of Capital Efficiency Gains} \subsubsection{Concentrated Liquidity} -In Astral, LPs can choose any of the following fees for their positions: 1\%, 0.3\%, 0.05\% and 0.01\%. Although users can choose any, it is recommended to use the following: +In \AstralWS, LPs can choose any of the following fees for their positions: 1\%, 0.3\%, 0.05\% and 0.01\%. Although users can choose any, it is recommended to use the following: \begin{itemize} \item 1\% for exotic/volatile tokens(e.g., SHIB, low caps); \item 0.3\% for most tokens(e.g., MATIC, AVAX); @@ -276,7 +286,7 @@ \subsubsection{Concentrated Liquidity} \end{itemize} LPs don\textsc{\char13}t need to follow this recommended fee structure. Still, traders are unlikely to accept high fees on low volatility assets, and holding exposure to exotic/volatile tokens without earning high fees will likely be unprofitable. Typical minimum and maximum gains depending on the fee level LPs set can be seen in Table \ref{table:CL_gains}. -\begin{table}[!h] +\begin{table}[!ht] \caption{Capital efficiency gains depending on the level of fee} \label{table:CL_gains} %\vskip 0.5cm @@ -310,6 +320,13 @@ \subsubsection{Concentrated Liquidity} \raisebox{-.9\height}{\includegraphics[width=\linewidth]{5bp}} & $20x \approx 400/20 $\\ +% ~ & +% Some stable coins & +% $\sim4000x$ & +% $2\% (\pm0.5\%)$ & +% \raisebox{-.9\height}{\includegraphics[width=\linewidth]{5bp-st}} & +% $200x \approx 400/2$ \\ + $fee = 1bp = 0.01\%$ $fee/1bp = 0.01\% bin$ \textemdash \ Choice for stablecoins & Stable coins & $\sim40,000x$ & @@ -327,7 +344,7 @@ \subsubsection{Single Pool Contracts} SPC\textsc{\char13}s capital efficiency gains depending on the level of users can be seen in Table \ref{table:spc_gains}. -\begin{table}[!h] +\begin{table}[!ht] \caption{SPC\textsc{\char13}s capital efficiency gains depending on the level of users} \label{table:spc_gains} \vskip 0.5cm @@ -344,13 +361,13 @@ \subsubsection{Single Pool Contracts} \vskip 0.5cm N \textemdash \ number of assets; EN \textemdash \ effective number of assets. -*Note: Regarding the Future Advanced Use scenario, Astral has no dependency on the accuracy or rate of this scenario unfolding. This scenario is presented here mainly to illustrate how Astral\textsc{\char13}s model scales perfectly with the growth of the cryptocurrency sector, unlike current DEXs and CEXs, which do not have SPC. +*Note: Regarding the Future Advanced Use scenario, \Astral has no dependency on the accuracy or rate of this scenario unfolding. This scenario is presented here mainly to illustrate how \AstralWS\textsc{\char13}s model scales perfectly with the growth of the cryptocurrency sector, unlike current DEXs and CEXs, which do not have SPC. \end{table} \subsubsection{Single Token Liquidity} -Astral will offer 2x and 3x capital efficiency boosts to LPs through STL. In Astral, 2x from STL is a natural (though optional) benefit of the liquidity provision process as a result of how Astral\textsc{\char13}s STL utilizes vAUSD. In that regard, compared to current on-chain protocols for liquidity provision, Astral allows normal users to obtain higher capital efficiency through a smooth UX while protecting them with Astral\textsc{\char13}s triple-layered risk protection system (see section \ref{risk} for more information). +\Astral will offer 2x and 3x capital efficiency boosts to LPs through STL. In \AstralWS, 2x from STL is a natural (though optional) benefit of the liquidity provision process as a result of how \AstralWS\textsc{\char13}s STL utilizes vAUSD. In that regard, compared to current on-chain protocols for liquidity provision, \Astral allows normal users to obtain higher capital efficiency through a smooth UX while protecting them with \AstralWS\textsc{\char13}s triple-layered risk protection system (see section \ref{risk} for more information). -\begin{table}[!h] +\begin{table}[!ht] \caption{Capital efficiency gains with STL} \label{table:stl_gains} \vskip 0.5cm @@ -362,8 +379,8 @@ \subsubsection{Single Token Liquidity} Binance Equity & 3-10x & 3-10x \\ Binance Futures & 20x & 20-125x \\ Classical Stock Market & 1x (no margin) & 2-4x (6x for ETFs) \\ -Astral v1 & 2x & 3x \\ -Astral v2+ (with oracles) & 2-3x & 4-5x\\ +\Astral v1 & 2x & 3x \\ +\Astral v2+ (with oracles) & 2-3x & 4-5x\\ \hline \end{tabular} \vskip 0.5cm @@ -371,17 +388,17 @@ \subsubsection{Single Token Liquidity} \end{table} \subsection{Realistic Benefits to Users} -Realistically, beyond 1000x, capital efficiency provides limited benefit to regular or advanced users. Therefore, while critically looking at these gains, we should ask ourselves how much benefit Astral provides in typical use cases and relative to industry competitors, which we will do below. +Realistically, beyond 1000x, capital efficiency provides limited benefit to regular or advanced users. Therefore, while critically looking at these gains, we should ask ourselves how much benefit \Astral provides in typical use cases and relative to industry competitors, which we will do below. -If a Uniswap V3 LP wants to achieve 200x efficiency, they have to add liquidity within the 2\% range. In contrast, Astral users will be able to accomplish this much easier and more naturally through the use of SPC and STL. At the minimum, the gain from these two components alone is 10x, reducing the demand on CL to only need to provide a 20x improvement instead of 200x. This, in turn, allows Astral\textsc{\char13}s LPs to achieve the same 200x efficiency while deploying liquidity in the 20\% range. +If a Uniswap V3 LP wants to achieve 200x efficiency, they have to add liquidity within the 2\% range. In contrast, \Astral users will be able to accomplish this much easier and more naturally through the use of SPC and STL. At the minimum, the gain from these two components alone is 10x, reducing the demand on CL to only need to provide a 20x improvement instead of 200x. This, in turn, allows \AstralWS\textsc{\char13}s LPs to achieve the same 200x efficiency while deploying liquidity in the 20\% range. For normal LPs, a range like 20\% allows them to utilize much more passive management of their positions because it decreases the frequency of needing to rebalance their positions and as a secondary effect, reduces aggregate gas spend. This translates to savings in cost and time, as well as reduced risk (of suffering large IL) for typical users. -For advanced LPs, since they typically prefer active management strategies, they would probably prefer the 2\% range, and Astral\textsc{\char13}s would boost their efficiency to 2000x instead of 200x, significantly increasing their yields as a result. +For advanced LPs, since they typically prefer active management strategies, they would probably prefer the 2\% range, and \AstralWS\textsc{\char13}s would boost their efficiency to 2000x instead of 200x, significantly increasing their yields as a result. For traders, the larger amount of liquidity deployed from the above LPs as a result of superior capital efficiency would mean a corresponding 10x decrease in price impact cost when swapping. -Finally, we note that these aforementioned benefits only consider Astral\textsc{\char13}s mathematically minimal capital efficiency improvement. It\textsc{\char13}s worth noting that Astral also provides much more flexibility: for LPs through STP, and for market makers and traders through AOTs. +Finally, we note that these aforementioned benefits only consider \AstralWS\textsc{\char13}s mathematically minimal capital efficiency improvement. It\textsc{\char13}s worth noting that \Astral also provides much more flexibility: for LPs through STP, and for market makers and traders through AOTs. \section{Concentrated Liquidity} \label{concentrated_liquidity} @@ -400,10 +417,10 @@ \subsubsection{Trident} Trident is an AMM launched by SushiSwap in 2022. Trident has four types of pools: Constant Product Pool, Hybrid Pool, Weighted Pool, and Concentrated Liquidity Pool. The latter gives LPs the ability to specify the price range of a token asset to add liquidity. LPs earn 0.25\% fees on all trades proportional to their pool share. Fees are added to the pool, accrue in real-time, and users can claim them by withdrawing liquidity \cite{Trident}. \ActivateWarningFilters[pdftoc] -\subsection{Concentrated Liquidity in Astral}\label{cl_Astral} +\subsection{Concentrated Liquidity in \Astral}\label{cl_Astral} \DeactivateWarningFilters[pdftoc] -In Astral\textsc{\char13}s CL implementation, the entire space of possible prices of TokenA in the pool is divided into sections by \textbf{ticks}. The price space between two adjacent ticks is a \textbf{bin}. When providing liquidity, the LP can choose the distance between any two ticks, forming the \textbf{price range}. Liquidity deployed into a specific range is called a \textbf{position}. Each tick is 0.01\% (1 basis point) away from neighbouring ticks. All possible price values p are initialized in ticks using a formula \cite{LiquidityMath}: +In \AstralWS\textsc{\char13}s CL implementation, the entire space of possible prices of TokenA in the pool is divided into sections by \textbf{ticks}. The price space between two adjacent ticks is a \textbf{bin}. When providing liquidity, the LP can choose the distance between any two ticks, forming the \textbf{price range}. Liquidity deployed into a specific range is called a \textbf{position}. Each tick is 0.01\% (1 basis point) away from neighbouring ticks. All possible price values p are initialized in ticks using a formula \cite{LiquidityMath}: \begin{center} $p(i) = 1.0001^i$, @@ -441,7 +458,7 @@ \subsection{Concentrated Liquidity in Astral}\label{cl_Astral} \end{itemize} \subsubsection{Concentrated Liquidity Swap} -Let\textsc{\char13}s do a simple swap without fees to understand the mechanics of CL\footnote{This example is presented to explain the basic principles of CL and does not fully reflect the algorithms of Astral.}. Suppose Alice wants to swap ETH for vAUSD using Astral\footnote{In Astral V1, vAUSD will not be mintable or directly tradeable. In a real case, Alice would swap ETH for USDT or another crypto asset. However, for simplicity\textsc{\char13}s sake, we show a swap between ETH and vAUSD in this example.}. In CL, the number of tokens in the pool is not required to calculate the number of tokens received in the exchange. The protocol must keep track of the $\Delta \sqrt{P}$ and $L$ in the pool. Suppose Alice wants to exchange just 1 ETH (then $\Delta y = 1$) for vAUSD in 0.3\% fee pool and there is enough liquidity in the pool ($x = 3,000,000$ vAUSD and $y = 1,000$ ETH). +Let\textsc{\char13}s do a simple swap without fees to understand the mechanics of CL\footnote{This example is presented to explain the basic principles of CL and does not fully reflect the algorithms of \AstralWS.}. Suppose Alice wants to swap ETH for vAUSD using \AstralWS\footnote{In \Astral V1, vAUSD will not be mintable or directly tradeable. In a real case, Alice would swap ETH for USDT or another crypto asset. However, for simplicity\textsc{\char13}s sake, we show a swap between ETH and vAUSD in this example.}. In CL, the number of tokens in the pool is not required to calculate the number of tokens received in the exchange. The protocol must keep track of the $\Delta \sqrt{P}$ and $L$ in the pool. Suppose Alice wants to exchange just 1 ETH (then $\Delta y = 1$) for vAUSD in 0.3\% fee pool and there is enough liquidity in the pool ($x = 3,000,000$ vAUSD and $y = 1,000$ ETH). \begin{center} $L = \sqrt{xy} = \sqrt{3,000,000,000} = 54,772.26$ @@ -486,7 +503,7 @@ \subsubsection{Concentrated Liquidity Swap} So Alice sells 1 ETH for 3,286.34 vAUSD. After this swap, the price will change but stay in the same bin. If Alice were to swap more ETH, the price could cross the tick. Then the swap would be executed in portions in the current and subsequent bins according to the price change. \section{Single Token Liquidity} -STL is a mechanic that allows the LPs to add only one token to the pool instead of providing pairs of tokens (STP), and then to achieve extra capital efficiency through matching vAUSD. This chapter reviews the STL-like mechanics in Bancor\textsc{\char13}s Centaur Swap to compare that protocol to Astral. +STL is a mechanic that allows the LPs to add only one token to the pool instead of providing pairs of tokens (STP), and then to achieve extra capital efficiency through matching vAUSD. This chapter reviews the STL-like mechanics in Bancor\textsc{\char13}s Centaur Swap to compare that protocol to \AstralWS. \subsection{Overview} \subsubsection{Centaur Swap (Bancor v2)} \label{centaurswap} @@ -505,21 +522,21 @@ \subsubsection{Centaur Swap (Bancor v2)} When users sell tokens in Bancor, the Current Balance of the pool increases, leading to a surplus of tokens. In this case, the pool must be rebalanced to the Target Balance. A discount is applied to encourage traders/arbitrageurs to buy more tokens. When users buy tokens, the Current Balance of the pool decreases, resulting in a Deficit of tokens. At this time, a premium will be applied to rebalance the pool. \ActivateWarningFilters[pdftoc] -\subsection{STL and SPC in Astral} +\subsection{STL and SPC in \AstralSubsection} \DeactivateWarningFilters[pdftoc] \label{stl} -Each liquidity pool in Astral consists of a TokenA (regular ERC20 token) paired with virtual stablecoin vAUSD. vAUSD is backed by all the assets in Astral pools and cannot be minted. All pools are created on the Astral side by initializing the starting price of a token (e.g. TokenA). When LPs add their tokens as liquidity to the pool, the corresponding amount of vAUSD is virtually matched for STL and a tracker for Virtual AUSD Balance is created. When users close their positions, vAUSD is returned to the protocol and the position\textsc{\char13}s Virtual AUSD Balance is reset to 0. +Each liquidity pool in \Astral consists of a TokenA (regular ERC20 token) paired with virtual stablecoin vAUSD. vAUSD is backed by all the assets in \Astral pools and cannot be minted. All pools are created on the \Astral side by initializing the starting price of a token (e.g. TokenA). When LPs add their tokens as liquidity to the pool, the corresponding amount of vAUSD is virtually matched for STL and a tracker for Virtual AUSD Balance is created. When users close their positions, vAUSD is returned to the protocol and the position\textsc{\char13}s Virtual AUSD Balance is reset to 0. -In order to avoid attacks from malicious tokens, only whitelisted tokens will allow for STL. Whitelisted tokens will be primarily composed of the top 50-100 tokens by mcap, which will have to pass through the Astral team\textsc{\char13}s risk analysis. These top tokens account for the vast majority of trading volume on exchanges. However, users will be able to LP any other non-whitelisted token, as is the case in other DEXs currently, and these tokens will still get the advantage of SPC. +In order to avoid attacks from malicious tokens, only whitelisted tokens will allow for STL. Whitelisted tokens will be primarily composed of the top 50-100 tokens by mcap, which will have to pass through the \Astral team\textsc{\char13}s risk analysis. These top tokens account for the vast majority of trading volume on exchanges. However, users will be able to LP any other non-whitelisted token, as is the case in other DEXs currently, and these tokens will still get the advantage of SPC. If the LP wants to add liquidity in a custom price range without matching with vAUSD, it is possible to open the position by providing an extra amount of any whitelisted token (using Single Token Provision). -Astral\textsc{\char13}s LPing with STL has a straightforward UX/UI design with a two-step process on the blockchain side, which is used in various endpoint functions. The UX/UI is made for easy use by beginners, with optional access to Astral\textsc{\char13}s full capabilities for experienced traders. +\AstralWS\textsc{\char13}s LPing with STL has a straightforward UX/UI design with a two-step process on the blockchain side, which is used in various endpoint functions. The UX/UI is made for easy use by beginners, with optional access to \AstralWS\textsc{\char13}s full capabilities for experienced traders. \subsubsection{Adding Liquidity} \label{addingliquidity} -When Astral creates a new pool, an initial price is set. If that pool is whitelisted, when a user adds liquidity to it, their deposited tokens can also use vAUSD matching for additional capital efficiency (which is optional). Then, Astral creates an LP position containing information about the position\textsc{\char13}s liquidity, price boundaries, and virtual AUSD balance. Subsequently, the user\textsc{\char13}s positions begins to accrue a proportional amount of fees relative to the position\textsc{\char13}s percentage of capital in the pool. Below, we examine the mathematics of liquidity provision with STL in more detail. +When \Astral creates a new pool, an initial price is set. If that pool is whitelisted, when a user adds liquidity to it, their deposited tokens can also use vAUSD matching for additional capital efficiency (which is optional). Then, \Astral creates an LP position containing information about the position\textsc{\char13}s liquidity, price boundaries, and virtual AUSD balance. Subsequently, the user\textsc{\char13}s positions begins to accrue a proportional amount of fees relative to the position\textsc{\char13}s percentage of capital in the pool. Below, we examine the mathematics of liquidity provision with STL in more detail. Suppose Alice wants to provide tokens. She adds 1 BTC to the liquidity pool. @@ -542,39 +559,39 @@ \subsubsection{Adding Liquidity} If LPs do not want to use STL, they can still use the Single Token Provision (STP) mechanic, which allows adding liquidity with one token. This would automatically swaps the necessary amount of TokenA for vAUSD to open a position. \subsubsection{Removing liquidity} -Users can get their liquidity back at any time, and the process would be the following. After removing liquidity from the pool of TokenA, the price of TokenA would remain the same. The position would return any outstanding vAUSD, accounted for in the Virtual AUSD Balance, to the protocol, and Astral would then virtually burn the vAUSD. The user would then receive their share of TokenA plus fees earned from the position in the form of TokenA. +Users can get their liquidity back at any time, and the process would be the following. After removing liquidity from the pool of TokenA, the price of TokenA would remain the same. The position would return any outstanding vAUSD, accounted for in the Virtual AUSD Balance, to the protocol, and \Astral would then virtually burn the vAUSD. The user would then receive their share of TokenA plus fees earned from the position in the form of TokenA. \subsubsection{Swapping} \label{swapping} -All tokens in each pool are paired with vAUSD. So when a user swaps TokenA for TokenB in the protocol, Astral uses vAUSD as a virtual intermediary in the background to transfer liquidity between TokenA and TokenB. To accomplish this, Astral utilizes internal half-swaps, swapping TokenA for vAUSD and then vAUSD for TokenB. This means swapping between any two tokens in Astral will never incur more than a single swap fee (the sum of two half-swaps). This is in contrast to the expensive mechanism of AMM pool-pairs in current DEXs, which not infrequently requires 3 or more swaps when executing a trade, due to liquidity being fragmented across many pools. +All tokens in each pool are paired with vAUSD. So when a user swaps TokenA for TokenB in the protocol, \Astral uses vAUSD as a virtual intermediary in the background to transfer liquidity between TokenA and TokenB. To accomplish this, \Astral utilizes internal half-swaps, swapping TokenA for vAUSD and then vAUSD for TokenB. This means swapping between any two tokens in \Astral will never incur more than a single swap fee (the sum of two half-swaps). This is in contrast to the expensive mechanism of AMM pool-pairs in current DEXs, which not infrequently requires 3 or more swaps when executing a trade, due to liquidity being fragmented across many pools. -In Astral, the trader never sees the background half-swaps using vAUSD. In the UX, they merely swap once between TokenA and TokenB and pay a single swap fee. This cost effective swapping is a major improvement over multi-hop swaps in other DEXs. We show an example below. +In \AstralWS, the trader never sees the background half-swaps using vAUSD. In the UX, they merely swap once between TokenA and TokenB and pay a single swap fee. This cost effective swapping is a major improvement over multi-hop swaps in other DEXs. We show an example below. Suppose Alice wants to swap TokenA for TokenB. In a typical DEX, this swap can be multi-hop (especially in the case where one of the tokens is not a top-traded token) like this: \begin{center} TokenA $\xrightarrow{\text{0.3\% swap fee}}$ TokenC $\xrightarrow{\text{0.3\% swap fee}}$ TokenB \end{center} - + or even a longer route: - + \begin{center} TokenA $\xrightarrow{\text{0.3\% swap fee}}$ TokenC $\xrightarrow{\text{0.3\% swap fee}}$ TokenD $\xrightarrow{\text{0.3\% swap fee}}$ TokenB \end{center} - -Meanwhile, through Astral, a swap requires only two half-swaps. - + +Meanwhile, through \AstralWS, a swap requires only two half-swaps. + \begin{center} TokenA $\xrightarrow{\text{0.15\% swap fee}} (vAUSD) \xrightarrow{\text{0.15\% swap fee}}$ TokenB \end{center} -Thus, Astral\textsc{\char13}s SPC decreases swap fees by at least 50\% when compared to multi-hop swaps on other DEXs, and in Astral\textsc{\char13}s UI, users only ever see a single swap between $TokenA \rightarrow TokenB$ for the standard swap fee of 0.3\%. +Thus, \AstralWS\textsc{\char13}s SPC decreases swap fees by at least 50\% when compared to multi-hop swaps on other DEXs, and in \AstralWS\textsc{\char13}s UI, users only ever see a single swap between $TokenA \rightarrow TokenB$ for the standard swap fee of 0.3\%. \ActivateWarningFilters[pdftoc] -\subsubsection{Advantages of SPC and STL in Astral} +\subsubsection{Advantages of SPC and STL in \AstralSubsubsection} \DeactivateWarningFilters[pdftoc] -SPC and STL are used in Astral, providing capital efficiency and simplicity for LPs. The liquidity for each token in Astral exists in a unified pool through SPC, and all liquidity pools consist of TokenA and virtual stablecoin vAUSD through STL. +SPC and STL are used in \AstralWS, providing capital efficiency and simplicity for LPs. The liquidity for each token in \Astral exists in a unified pool through SPC, and all liquidity pools consist of TokenA and virtual stablecoin vAUSD through STL. SPC and STL have the following advantages: \begin{enumerate} @@ -603,7 +620,7 @@ \subsubsection{Advantages of SPC and STL in Astral} \section{Risk Module: Advanced Risk Protection} \label{risk} -While STL, which is optional, offers increased capital efficiency, it also carries a higher exposure to impermanent loss, which can lead to LPs taking undesired equity losses from extreme price movements. At a certain point, this can even create an uncovered Virtual vAUSD Balance if left unchecked; if that were to happen, the protocol would suffer a shortfall with the LP\textsc{\char13}s position becoming unable to return a portion of the matched vAUSD. As a result, Astral makes sure to minimize this risk as much as possible both for LPs and the protocol, and it does this through a Triple-Layered Risk Protection Module. +While STL, which is optional, offers increased capital efficiency, it also carries a higher exposure to impermanent loss, which can lead to LPs taking undesired equity losses from extreme price movements. At a certain point, this can even create an uncovered Virtual vAUSD Balance if left unchecked; if that were to happen, the protocol would suffer a shortfall with the LP\textsc{\char13}s position becoming unable to return a portion of the matched vAUSD. As a result, \Astral makes sure to minimize this risk as much as possible both for LPs and the protocol, and it does this through a Triple-Layered Risk Protection Module. \subsection{Triple-Layer Risk Protection Module} \subsubsection{Stop-Loss}\label{stop-loss} @@ -613,14 +630,14 @@ \subsubsection{Repurchase} The second layer of protection is the repurchase system, which has two core terms: \begin{itemize} - \item vAUSD Balance Ratio: the ratio of Virtual AUSD Balance to the total value of the position. Astral\textsc{\char13}s typical 2x STL use-case starts with a vAUSD Balance Ratio of 0.5; - \item Bounty Fee: A fee the LP pays if a repurchase on their position was activated and a keeper\footnote{A keeper is a 3rd-party that helps preserve an ecosystem\textsc{\char13}s health by participating in certain related maintenance activities, which in Astral, are repurchasing and virtual rebalancing.} executed it. + \item vAUSD Balance Ratio: the ratio of Virtual AUSD Balance to the total value of the position. \AstralWS\textsc{\char13}s typical 2x STL use-case starts with a vAUSD Balance Ratio of 0.5; + \item Bounty Fee: A fee the LP pays if a repurchase on their position was activated and a keeper\footnote{A keeper is a 3rd-party that helps preserve an ecosystem\textsc{\char13}s health by participating in certain related maintenance activities, which in \AstralWS, are repurchasing and virtual rebalancing.} executed it. \end{itemize} A repurchase is required when a liquidity position\textsc{\char13}s value drops and its vAUSD Balance Ratio rises above the Repurchase Threshold (for which the default value is 0.75 in our protocol). Once this happens, a 3rd-party keeper can come in and execute a repurchase on the position, which involves repaying the virtual AUSD Balance and closing the position in exchange for the Bounty Fee (default at 1\% of the TokenA value at position closing). The remaining amount in the position would then be returned to the liquidity provider. \subsubsection{Virtual rebalance} -Virtual Rebalance is the last measure in Astral\textsc{\char13}s Risk Protection Module, which would trigger if the user did not set a stop-loss and a repurchase did not execute in time. The vAUSD Balance Ratio above which a virtual rebalance would occur (Virtual Rebalance Threshold) will have a starting setting of 0.8, and the keeper executing it would get a Bounty Fee of 5\% of the TokenA value. The higher Bounty Fee and a low Virtual Rebalance Threshold are set as such to minimize the chance of an uncovered balance and encourage LPs to set stop-losses. 3rd-party trusted keepers will be allowed to act as rebalancers and repurchasers. +Virtual Rebalance is the last measure in \AstralWS\textsc{\char13}s Risk Protection Module, which would trigger if the user did not set a stop-loss and a repurchase did not execute in time. The vAUSD Balance Ratio above which a virtual rebalance would occur (Virtual Rebalance Threshold) will have a starting setting of 0.8, and the keeper executing it would get a Bounty Fee of 5\% of the TokenA value. The higher Bounty Fee and a low Virtual Rebalance Threshold are set as such to minimize the chance of an uncovered balance and encourage LPs to set stop-losses. 3rd-party trusted keepers will be allowed to act as rebalancers and repurchasers. In the case of a virtual rebalance, 25\% of the position would be converted to return some of the matched vAUSD to keep the position healthy, the bounty would be paid to the virtual rebalancer, and the remaining tokens would stay in the still open LP position, continuing to accrue yields. @@ -630,24 +647,24 @@ \subsubsection{Virtual rebalance} \subsection{Insurance Plan} -While the triple-layered approach to risk mitigation should be significantly useful for LPs, Astral will also have an Insurance Plan to deal with any potential shortfall that could theoretically arise, such as smart contract risk or an uncovered balance. This Insurance Plan will provide an additional layer of cover to users\textsc{\char13} capital in the protocol. Should a shortfall occur, it will be covered by future earnings over time until made whole. These funds would come from a percentage of protocol earnings shared with governance lockup stakers, who will receive the earnings in exchange for providing this backstop cover. This is similar to the Safety Module featured by Aave\cite{aave}. +While the triple-layered approach to risk mitigation should be significantly useful for LPs, \Astral will also have an Insurance Plan to deal with any potential shortfall that could theoretically arise, such as smart contract risk or an uncovered balance. This Insurance Plan will provide an additional layer of cover to users\textsc{\char13} capital in the protocol. Should a shortfall occur, it will be covered by future earnings over time until made whole. These funds would come from a percentage of protocol earnings shared with governance lockup stakers, who will receive the earnings in exchange for providing this backstop cover. This is similar to the Safety Module featured by Aave\cite{aave}. \section{Flexibility and Multi-purpose} -One of the key advantages of Astral over Uniswap, Sushiswap, Pancakeswap, 1inch, and other DEX protocols is Astral\textsc{\char13}s flexibility and multi-purpose approach. +One of the key advantages of \Astral over Uniswap, Sushiswap, Pancakeswap, 1inch, and other DEX protocols is \AstralWS\textsc{\char13}s flexibility and multi-purpose approach. One of the main challenges for first-time users in providing liquidity is the need to have a pair of two equivalently valued tokens. STL solves this problem and supports freeing up capital from different pools for advanced users. -STL also simplifies the LP process (matching vAUSD for LPs). In Uniswap V3, LPs must specify exact price ranges for liquidity provision. This can be tricky, especially for novice users. Astral\textsc{\char13}s UI shows all assets in the user\textsc{\char13}s wallet that can be used to provide liquidity and allows users to add all these assets as liquidity within one transaction. In V2, Astral will also allow adding liquidity without thinking about the concentrated liquidity range because the UI will optimize the range for users. All functionality for adding liquidity and using STL will be on one page for convenience. In most cases, after the user sends all their assets into their Web3 wallet, they will only need to click one button to start earning yields with them all. This is called One-Click LP. +STL also simplifies the LP process (matching vAUSD for LPs). In Uniswap V3, LPs must specify exact price ranges for liquidity provision. This can be tricky, especially for novice users. \AstralWS\textsc{\char13}s UI shows all assets in the user\textsc{\char13}s wallet that can be used to provide liquidity and allows users to add all these assets as liquidity within one transaction. In V2, \Astral will also allow adding liquidity without thinking about the concentrated liquidity range because the UI will optimize the range for users. All functionality for adding liquidity and using STL will be on one page for convenience. In most cases, after the user sends all their assets into their Web3 wallet, they will only need to click one button to start earning yields with them all. This is called One-Click LP. CLOs and at-tick Segments allow for more advanced features for more professional users. Ticks provide a good DEX-equivalent of limit orders, while the bins in CLOs provide a valuable primitive analogous to spread out orders in centralized exchanges. LP in the at-tick segment also allows for interesting mechanics for pegging prices. -With these features, Astral provides a superset of the use cases allowed by both modern DEXs and CEXs. Given this wide range of flexibility is delivered in an optimized contract architecture and simple-to-use UI, and the fact that Astral\textsc{\char13}s model is the most capital efficient on the market, providing higher earnings to LPs and lower swap costs to traders, Astral is the most state-of-the-art DEX on the market, providing a new peak of value for both retail and professional market makers and traders. +With these features, \Astral provides a superset of the use cases allowed by both modern DEXs and CEXs. Given this wide range of flexibility is delivered in an optimized contract architecture and simple-to-use UI, and the fact that \AstralWS\textsc{\char13}s model is the most capital efficient on the market, providing higher earnings to LPs and lower swap costs to traders, \Astral is the most state-of-the-art DEX on the market, providing a new peak of value for both retail and professional market makers and traders. -Lastly, since Astral\textsc{\char13}s SPC model is more scalable than the current DEXs on the market, Astral is also the most forward-looking DEX, for which its advantage will continue to grow in line with the growth of the cryptocurrency market. +Lastly, since \AstralWS\textsc{\char13}s SPC model is more scalable than the current DEXs on the market, \Astral is also the most forward-looking DEX, for which its advantage will continue to grow in line with the growth of the cryptocurrency market. \section{Future Improvements} -In future versions of Astral, we aim to add the following features to help improve LPs\textsc{\char13} and traders\textsc{\char13} experience. +In future versions of \AstralWS, we aim to add the following features to help improve LPs\textsc{\char13} and traders\textsc{\char13} experience. \subsection{Borrowing of Any Whitelisted Tokens} \label{whitelisted-borrowing} @@ -673,19 +690,19 @@ \subsection{LP Automation} % Alpaca protocol has already successfully launched a limited version of their internal auto-hedging that rebalances delta-neutral position if it accumulates delta exposure. See \cite{alpaca} for more details. We will avoid a deep dive into the subject of impermanent loss but see the following reference for more detail \cite{impermanentLoss}. \section{Conclusion} -Astral provides cutting edge DEX capabilities (CL, SPC, STL, AOT, and Advanced Risk Protection). This adds tremendous value to exchange users through higher capital efficiency, coming primarily from the innovative combination of three advanced features: CL, SPC and STL. Compared to the most capitally efficient DEX on the market, Uniswap V3, Astral currently offers a capital efficiency improvement of a minimum of 10-20x for typical use cases. For advanced use cases, Astral can offer up to a 500x improvement over Uniswap V3, which can organically scale up to a realistic theoretical upper bound of 50,000x with the growth of the cryptocurrency market (more details in section \ref{superior-ce}). +\Astral provides cutting edge DEX capabilities (CL, SPC, STL, AOT, and Advanced Risk Protection). This adds tremendous value to exchange users through higher capital efficiency, coming primarily from the innovative combination of three advanced features: CL, SPC and STL. Compared to the most capitally efficient DEX on the market, Uniswap V3, \Astral currently offers a capital efficiency improvement of a minimum of 10-20x for typical use cases. For advanced use cases, \Astral can offer up to a 500x improvement over Uniswap V3, which can organically scale up to a realistic theoretical upper bound of 50,000x with the growth of the cryptocurrency market (more details in section \ref{superior-ce}). -For traders, Astral\textsc{\char13}s improved capital efficiency from its sophisticated features results in cheaper swap costs due to lower price impact and a single fee on multi-hop swaps between any two tokens. +For traders, \AstralWS\textsc{\char13}s improved capital efficiency from its sophisticated features results in cheaper swap costs due to lower price impact and a single fee on multi-hop swaps between any two tokens. -In addition to better capital efficiency, Astral provides greater user flexibility than existing DEXs thanks to its AOTs and STL. AOTs allow for traders and market makers to use a wide range of strategies and orders, analogous to those provided by centralized exchanges. As for STL, it removes the need to use pairs of tokens in liquidity contracts, allowing liquidity providers to add liquidity with only one asset, simplifying the user experience. +In addition to better capital efficiency, \Astral provides greater user flexibility than existing DEXs thanks to its AOTs and STL. AOTs allow for traders and market makers to use a wide range of strategies and orders, analogous to those provided by centralized exchanges. As for STL, it removes the need to use pairs of tokens in liquidity contracts, allowing liquidity providers to add liquidity with only one asset, simplifying the user experience. -In summary, what makes Astral the cutting edge of DEXs is that it combines and improves all the capabilities of current centralized and decentralized exchanges, all in one easy-to-use DEX that is fully on-chain. Its advantages from proprietary technology are not only currently significant but will organically expand with the cryptocurrency market, putting it in a position to gain growing success in the long-term. +In summary, what makes \Astral the cutting edge of DEXs is that it combines and improves all the capabilities of current centralized and decentralized exchanges, all in one easy-to-use DEX that is fully on-chain. Its advantages from proprietary technology are not only currently significant but will organically expand with the cryptocurrency market, putting it in a position to gain growing success in the long-term. \clearpage \section{Appendix A: Invariants} \begin{table}[h] -\caption{Invariants in Astral} +\caption{Invariants in \Astral} \label{table:leverage_gains} \vskip 0.5cm \centering @@ -733,7 +750,7 @@ \section{Glossary} \textbf{Single Token Liquidity (STL):} a mechanic that allows liquidity providers to provide only one token to open a position(Single Token Provision; STP). The liquidity can then be paired with vAUSD in a smart contract (vAUSD Matching). -\textbf{Virtual AUSD (vAUSD):} the virtual stablecoin AUSD, existing within Astral for the purpose of acting as an intermediary unit of account that facilitates STL and SPC. vAUSD is backed by all the assets in Astral pools, but is not mintable or directly tradable. +\textbf{Virtual AUSD (vAUSD):} the virtual stablecoin AUSD, existing within \Astral for the purpose of acting as an intermediary unit of account that facilitates STL and SPC. vAUSD is backed by all the assets in \Astral pools, but is not mintable or directly tradable. % \textbf{Grid trading:} a strategy that involves placing buy and sell orders at set intervals around a set price. A grid can be created to profit from trend breakouts (buy orders are placed above a set price and sell orders are placed below) or range consolidations (buy orders are placed below a set price and sell orders are placed above). From 1780fe464b4b3c5bdabb857e18c3a4197370a46b Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Mon, 6 Feb 2023 14:11:25 +0100 Subject: [PATCH 2/7] chore: improve repurchase description + update date --- whitepaper/ALDEX_Whitepaper_VC_version.tex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/whitepaper/ALDEX_Whitepaper_VC_version.tex b/whitepaper/ALDEX_Whitepaper_VC_version.tex index 85ae7f1..8f1797c 100644 --- a/whitepaper/ALDEX_Whitepaper_VC_version.tex +++ b/whitepaper/ALDEX_Whitepaper_VC_version.tex @@ -30,7 +30,8 @@ \title{\AstralTitle DEX Whitepaper} \author{\AstralSubtitle Research Team} -\date{\today} + +\date{August 29, 2022 \\ {\footnotesize Last updated: \today}} \hypersetup{pdfauthor={Name}} @@ -634,7 +635,7 @@ \subsubsection{Repurchase} \item Bounty Fee: A fee the LP pays if a repurchase on their position was activated and a keeper\footnote{A keeper is a 3rd-party that helps preserve an ecosystem\textsc{\char13}s health by participating in certain related maintenance activities, which in \AstralWS, are repurchasing and virtual rebalancing.} executed it. \end{itemize} -A repurchase is required when a liquidity position\textsc{\char13}s value drops and its vAUSD Balance Ratio rises above the Repurchase Threshold (for which the default value is 0.75 in our protocol). Once this happens, a 3rd-party keeper can come in and execute a repurchase on the position, which involves repaying the virtual AUSD Balance and closing the position in exchange for the Bounty Fee (default at 1\% of the TokenA value at position closing). The remaining amount in the position would then be returned to the liquidity provider. +A repurchase is required when a liquidity position\textsc{\char13}s value drops and its vAUSD Balance Ratio rises above the Repurchase Threshold (for which the default value is 0.75 in our protocol). Once this happens, a 3rd-party keeper can come in and execute a repurchase on the position, which involves repaying the excess amount of the virtual AUSD Balance and transferring the position to the repurchaser in exchange for the value of the LP position (minus prior virtual AUSD balance and the Bounty Fee; default at 1\% of the position value at position closing). \subsubsection{Virtual rebalance} Virtual Rebalance is the last measure in \AstralWS\textsc{\char13}s Risk Protection Module, which would trigger if the user did not set a stop-loss and a repurchase did not execute in time. The vAUSD Balance Ratio above which a virtual rebalance would occur (Virtual Rebalance Threshold) will have a starting setting of 0.8, and the keeper executing it would get a Bounty Fee of 5\% of the TokenA value. The higher Bounty Fee and a low Virtual Rebalance Threshold are set as such to minimize the chance of an uncovered balance and encourage LPs to set stop-losses. 3rd-party trusted keepers will be allowed to act as rebalancers and repurchasers. From 617a877ce99ff7ceaabf263efdd28c1d4ca1710e Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Mon, 6 Feb 2023 15:24:51 +0100 Subject: [PATCH 3/7] chore: edits from Sam regarding Four-Layered Rebalancing System --- whitepaper/ALDEX_Whitepaper_VC_version.tex | 39 ++++++++++++---------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/whitepaper/ALDEX_Whitepaper_VC_version.tex b/whitepaper/ALDEX_Whitepaper_VC_version.tex index 8f1797c..dbb22a3 100644 --- a/whitepaper/ALDEX_Whitepaper_VC_version.tex +++ b/whitepaper/ALDEX_Whitepaper_VC_version.tex @@ -87,7 +87,7 @@ \section{Introduction} \subsection{What is \AstralSubsection?} \label{whatisAstral} \DeactivateWarningFilters[pdftoc] -\Astral DEX (\AstralWS) is a cutting edge decentralized exchange (DEX)\footnote{Decentralized exchanges (DEXs) are a cornerstone of DeFi. DEXs are peer-to-peer marketplaces where transactions occur directly between crypto traders without requiring an intermediary.} that combines and improves the functionalities of existing decentralized and centralized exchanges. \Astral combines advanced features, including Concentrated Liquidity (CL), Single Pool Contracts (SPC), Single Token Liquidity (STL), Advanced Order Types (AOT), and Triple-Layered Risk Protection, to create a versatile and powerful DEX which tremendously improves capital efficiency\footnote{Capital efficiency is how effectively capital is utilized to generate returns or meet production goals. For example, \$1 of capital that produces \$1 in returns is more capital efficient than \$1 that produces \$0.10 in returns if both are utilizing the same investment strategy.} and ease of use, offering users lower swap costs and a better user experience. +\Astral DEX (\AstralWS) is a cutting edge decentralized exchange (DEX)\footnote{Decentralized exchanges (DEXs) are a cornerstone of DeFi. DEXs are peer-to-peer marketplaces where transactions occur directly between crypto traders without requiring an intermediary.} that combines and improves the functionalities of existing decentralized and centralized exchanges. \Astral combines advanced features, including Concentrated Liquidity (CL), Single Pool Contracts (SPC), Single Token Liquidity (STL), Advanced Order Types (AOT), and Four-Layered Rebalancing System, to create a versatile and powerful DEX which tremendously improves capital efficiency\footnote{Capital efficiency is how effectively capital is utilized to generate returns or meet production goals. For example, \$1 of capital that produces \$1 in returns is more capital efficient than \$1 that produces \$0.10 in returns if both are utilizing the same investment strategy.} and ease of use, offering users lower swap costs and a better user experience. For those unfamiliar with the field, this introduction will provide a broad overview of the key concepts and developments related to \AstralWS. @@ -366,7 +366,7 @@ \subsubsection{Single Pool Contracts} \end{table} \subsubsection{Single Token Liquidity} -\Astral will offer 2x and 3x capital efficiency boosts to LPs through STL. In \AstralWS, 2x from STL is a natural (though optional) benefit of the liquidity provision process as a result of how \AstralWS\textsc{\char13}s STL utilizes vAUSD. In that regard, compared to current on-chain protocols for liquidity provision, \Astral allows normal users to obtain higher capital efficiency through a smooth UX while protecting them with \AstralWS\textsc{\char13}s triple-layered risk protection system (see section \ref{risk} for more information). +\Astral will offer 2x and 3x capital efficiency boosts to LPs through STL. In \AstralWS, 2x from STL is a natural (though optional) benefit of the liquidity provision process as a result of how \AstralWS\textsc{\char13}s STL utilizes vAUSD. In that regard, compared to current on-chain protocols for liquidity provision, \Astral allows normal users to obtain higher capital efficiency through a smooth UX while protecting them with \AstralWS\textsc{\char13}s Four-Layered Rebalancing System (see section \ref{risk} for more information). \begin{table}[!ht] \caption{Capital efficiency gains with STL} @@ -618,37 +618,42 @@ \subsubsection{Advantages of SPC and STL in \AstralSubsubsection} \end{itemize} \end{enumerate} -\section{Risk Module: Advanced Risk Protection} +\section{Four-Layered Rebalancing System} \label{risk} -While STL, which is optional, offers increased capital efficiency, it also carries a higher exposure to impermanent loss, which can lead to LPs taking undesired equity losses from extreme price movements. At a certain point, this can even create an uncovered Virtual vAUSD Balance if left unchecked; if that were to happen, the protocol would suffer a shortfall with the LP\textsc{\char13}s position becoming unable to return a portion of the matched vAUSD. As a result, \Astral makes sure to minimize this risk as much as possible both for LPs and the protocol, and it does this through a Triple-Layered Risk Protection Module. +While STL, which is optional, offers increased capital efficiency, it also carries a higher exposure to impermanent loss, which can lead to LPs taking undesired equity losses from extreme price movements. At a certain point, this can even create an uncovered Virtual vAUSD Balance if left unchecked; although extremely unlikely mathematically, if that were to happen, the protocol would suffer a shortfall with the LP\textsc{\char13}s position becoming unable to return a portion of the matched vAUSD. As a result, \Astral makes sure to minimize this risk as much as possible both for LPs and the protocol, and it does this through a Four-Layered Rebalancing System. + +\subsection{Four-Layered Rebalancing System} +\subsubsection{Manual Rebalancing}\label{manual-rebalancing} +At the top layer, LPs can and are encouraged to manually rebalance their positions when necessary in order to maintain their ideal liquidity ranges and capital efficiency boosts, and minimize potential impermanent loss from significant price movements. + +In a future version, we plan for \AstralWS to offer automated management of custom ranges for rebalancing and concentrated liquidity. -\subsection{Triple-Layer Risk Protection Module} \subsubsection{Stop-Loss}\label{stop-loss} -As the first protection layer, an LP can set a customized stop-loss, which if triggered, would automatically close their position. This can allow the LP to better control their liquidity range and prevent paying a bounty from a repurchase or virtual rebalance that could occur if token price continued to move against their position. +As the first automated protection layer, an LP can set a customized stop-loss, which if triggered, would automatically close their position. This can allow the LP to better control their liquidity range and prevent paying a bounty from a keeper-rebalance or auto-rebalance that could occur if token price continued to move downwards without a rebalance. -\subsubsection{Repurchase} -The second layer of protection is the repurchase system, which has two core terms: +\subsubsection{Keeper-Rebalancing} +The second layer of protection is the Keeper-Rebalancing system, which has two core terms: \begin{itemize} \item vAUSD Balance Ratio: the ratio of Virtual AUSD Balance to the total value of the position. \AstralWS\textsc{\char13}s typical 2x STL use-case starts with a vAUSD Balance Ratio of 0.5; - \item Bounty Fee: A fee the LP pays if a repurchase on their position was activated and a keeper\footnote{A keeper is a 3rd-party that helps preserve an ecosystem\textsc{\char13}s health by participating in certain related maintenance activities, which in \AstralWS, are repurchasing and virtual rebalancing.} executed it. + \item Bounty Fee: A fee the LP pays if a keeper-rebalance on their position was activated and a keeper\footnote{A keeper is a 3rd-party that helps preserve an ecosystem\textsc{\char13}s health by participating in certain related maintenance activities, which in \AstralWS, are keeper-rebalancing and auto-rebalancing.} executed it. \end{itemize} -A repurchase is required when a liquidity position\textsc{\char13}s value drops and its vAUSD Balance Ratio rises above the Repurchase Threshold (for which the default value is 0.75 in our protocol). Once this happens, a 3rd-party keeper can come in and execute a repurchase on the position, which involves repaying the excess amount of the virtual AUSD Balance and transferring the position to the repurchaser in exchange for the value of the LP position (minus prior virtual AUSD balance and the Bounty Fee; default at 1\% of the position value at position closing). +A rebalance is required when a liquidity position\textsc{\char13}s value drops and its vAUSD Balance Ratio rises above the Rebalance Threshold (for which the default value is 0.75 in our protocol). Once this happens, a 3rd-party keeper can come in and execute a rebalance on the position, which involves repaying the excess amount of the virtual AUSD Balance and transferring the position to the keeper in exchange for the value of the LP position (minus prior virtual AUSD balance and the Bounty Fee; default at 1\% of the position value at position closing). -\subsubsection{Virtual rebalance} -Virtual Rebalance is the last measure in \AstralWS\textsc{\char13}s Risk Protection Module, which would trigger if the user did not set a stop-loss and a repurchase did not execute in time. The vAUSD Balance Ratio above which a virtual rebalance would occur (Virtual Rebalance Threshold) will have a starting setting of 0.8, and the keeper executing it would get a Bounty Fee of 5\% of the TokenA value. The higher Bounty Fee and a low Virtual Rebalance Threshold are set as such to minimize the chance of an uncovered balance and encourage LPs to set stop-losses. 3rd-party trusted keepers will be allowed to act as rebalancers and repurchasers. +\subsubsection{Auto-Rebalancing} +Auto-Rebalancing is the last measure in \AstralWS\textsc{\char13}s Rebalancing System, which would trigger if the user did not manually rebalance, did not set a stop-loss and a keeper did not execute a rebalance in time. The vAUSD Balance Ratio above which an auto-rebalance would occur (Auto-Rebalance Threshold) will have a starting setting of 0.8, and the keeper executing it would get a Bounty Fee of 5\% of the TokenA value. The higher Bounty Fee and a low Auto-Rebalance Threshold are set as such to minimize the chance of an uncovered balance and encourage LPs to manually rebalance or set stop-losses. 3rd-party trusted keepers will be allowed to act as rebalancers and for keeper-rebalancing and auto-rebalancing. -In the case of a virtual rebalance, 25\% of the position would be converted to return some of the matched vAUSD to keep the position healthy, the bounty would be paid to the virtual rebalancer, and the remaining tokens would stay in the still open LP position, continuing to accrue yields. +Note that an auto-rebalance is only a partial adjustment on the position. In the case of an auto-rebalance, 25\% of the position would be converted to return some of the matched vAUSD to keep the position healthy, the bounty would be paid to the auto-rebalancer, and the remaining tokens would stay in the still open LP position, continuing to accrue yields. -While the virtual rebalance layer is the last level of defence, ideally, this layer would never get activated. A stop-loss or repurchase would execute first, protecting LPs from paying a bounty and undesired price impact from closing their positions during periods of extreme market volatility. +While the auto-rebalance layer is the last layer, ideally, this would never get activated. A manual rebalance, stop-loss or keeper-rebalance would execute first, protecting LPs from undesirable IL, paying a bounty, and undesired price impact from closing their positions during periods of extreme market volatility. -Finally, note that repurchasing and virtual rebalancing cannot occur for positions that do not utilize STL, and even in those that do, these layers are only for backup protection and not intended to activate under normal conditions. +Finally, note that keeper-rebalancing and auto-rebalancing cannot occur for positions that do not utilize STL, and even in those that do, these layers are only for backup protection and not intended to activate under normal conditions. \subsection{Insurance Plan} -While the triple-layered approach to risk mitigation should be significantly useful for LPs, \Astral will also have an Insurance Plan to deal with any potential shortfall that could theoretically arise, such as smart contract risk or an uncovered balance. This Insurance Plan will provide an additional layer of cover to users\textsc{\char13} capital in the protocol. Should a shortfall occur, it will be covered by future earnings over time until made whole. These funds would come from a percentage of protocol earnings shared with governance lockup stakers, who will receive the earnings in exchange for providing this backstop cover. This is similar to the Safety Module featured by Aave\cite{aave}. +While the four-layered approach to risk mitigation should be significantly useful for LPs, \Astral will also have an Insurance Plan to deal with any potential shortfall that could theoretically arise, such as smart contract risk or an uncovered balance. This Insurance Plan will provide an additional layer of cover to users\textsc{\char13} capital in the protocol. Should a shortfall occur, it will be covered by future earnings over time until made whole. These funds would come from a percentage of protocol earnings shared with governance lockup stakers, who will receive the earnings in exchange for providing this backstop cover. This is similar to the Safety Module featured by Aave\cite{aave}. \section{Flexibility and Multi-purpose} One of the key advantages of \Astral over Uniswap, Sushiswap, Pancakeswap, 1inch, and other DEX protocols is \AstralWS\textsc{\char13}s flexibility and multi-purpose approach. @@ -691,7 +696,7 @@ \subsection{LP Automation} % Alpaca protocol has already successfully launched a limited version of their internal auto-hedging that rebalances delta-neutral position if it accumulates delta exposure. See \cite{alpaca} for more details. We will avoid a deep dive into the subject of impermanent loss but see the following reference for more detail \cite{impermanentLoss}. \section{Conclusion} -\Astral provides cutting edge DEX capabilities (CL, SPC, STL, AOT, and Advanced Risk Protection). This adds tremendous value to exchange users through higher capital efficiency, coming primarily from the innovative combination of three advanced features: CL, SPC and STL. Compared to the most capitally efficient DEX on the market, Uniswap V3, \Astral currently offers a capital efficiency improvement of a minimum of 10-20x for typical use cases. For advanced use cases, \Astral can offer up to a 500x improvement over Uniswap V3, which can organically scale up to a realistic theoretical upper bound of 50,000x with the growth of the cryptocurrency market (more details in section \ref{superior-ce}). +\Astral provides cutting edge DEX capabilities (CL, SPC, STL, AOT, and Four-Layered Rebalancing System). This adds tremendous value to exchange users through higher capital efficiency, coming primarily from the innovative combination of three advanced features: CL, SPC and STL. Compared to the most capitally efficient DEX on the market, Uniswap V3, \Astral currently offers a capital efficiency improvement of a minimum of 10-20x for typical use cases. For advanced use cases, \Astral can offer up to a 500x improvement over Uniswap V3, which can organically scale up to a realistic theoretical upper bound of 50,000x with the growth of the cryptocurrency market (more details in section \ref{superior-ce}). For traders, \AstralWS\textsc{\char13}s improved capital efficiency from its sophisticated features results in cheaper swap costs due to lower price impact and a single fee on multi-hop swaps between any two tokens. From 4664d93b1f34fb6cb1f22ce80ce6747cb09426ed Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Mon, 6 Feb 2023 15:28:39 +0100 Subject: [PATCH 4/7] chore: fix space after astral name --- whitepaper/ALDEX_Whitepaper_VC_version.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/whitepaper/ALDEX_Whitepaper_VC_version.tex b/whitepaper/ALDEX_Whitepaper_VC_version.tex index dbb22a3..2b01cea 100644 --- a/whitepaper/ALDEX_Whitepaper_VC_version.tex +++ b/whitepaper/ALDEX_Whitepaper_VC_version.tex @@ -627,7 +627,7 @@ \subsection{Four-Layered Rebalancing System} \subsubsection{Manual Rebalancing}\label{manual-rebalancing} At the top layer, LPs can and are encouraged to manually rebalance their positions when necessary in order to maintain their ideal liquidity ranges and capital efficiency boosts, and minimize potential impermanent loss from significant price movements. -In a future version, we plan for \AstralWS to offer automated management of custom ranges for rebalancing and concentrated liquidity. +In a future version, we plan for \Astral to offer automated management of custom ranges for rebalancing and concentrated liquidity. \subsubsection{Stop-Loss}\label{stop-loss} As the first automated protection layer, an LP can set a customized stop-loss, which if triggered, would automatically close their position. This can allow the LP to better control their liquidity range and prevent paying a bounty from a keeper-rebalance or auto-rebalance that could occur if token price continued to move downwards without a rebalance. From a4f1e5a5c4e1130cd826b9c42efdbc44e2d24022 Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Mon, 13 Mar 2023 10:08:14 +0100 Subject: [PATCH 5/7] chore: add tests for generated values --- contracts/tests/base/FullTest.sol | 23 + .../AldexBank/openPositionWithSwapForUI.sol | 801 ++++++++++++++++++ 2 files changed, 824 insertions(+) create mode 100644 contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol diff --git a/contracts/tests/base/FullTest.sol b/contracts/tests/base/FullTest.sol index ad4ba8c..1b0b1d0 100644 --- a/contracts/tests/base/FullTest.sol +++ b/contracts/tests/base/FullTest.sol @@ -359,6 +359,29 @@ abstract contract FullTest is BaseTest, TestUtils { ); } + function createTokenAndDeployPoolWithPrice( + address tokenOwner, + string memory coinName, + string memory coinAbbr, + uint8 decimals, + uint24 tokenSwapFee, + uint24 tokenTickSpacing, + uint160 sqrtPriceX96 + ) internal returns (TokenMeta memory tokenMeta) { + PoolMeta memory poolMeta = PoolMeta( + tokenSwapFee, + tokenTickSpacing, + sqrtPriceX96 + ); + tokenMeta = _createTokenAndDeployPool( + tokenOwner, + coinName, + coinAbbr, + decimals, + poolMeta + ); + } + // todo: consider refactoring: extract logic of createTokenAndDeployPool and createTokenAndDeployFakePool function createTokenAndDeployFakePool( address tokenOwner, diff --git a/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol b/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol new file mode 100644 index 0000000..d6cadc1 --- /dev/null +++ b/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol @@ -0,0 +1,801 @@ +// TODO: license +pragma solidity 0.8.17; +// utils +import { console } from "./../../base/BaseTest.sol"; +// interfaces +import { IConcentratedLiquidityPoolStruct } from "../../../v0.8.17/interfaces/IConcentratedLiquidityPool.sol"; +import { IUserPosition } from "../../../v0.8.17/interfaces/IUserPosition.sol"; +// libraries +import { UnsafeMath } from "../../../v0.8.17/libraries/UnsafeMath.sol"; +import { TickMath } from "../../../v0.8.17/libraries/TickMath.sol"; +import { FullMath } from "../../../v0.8.17/libraries/FullMath.sol"; +import { AldexMath } from "../../../v0.8.17/libraries/AldexMath.sol"; +// implementation +import { FullTest } from "./../../base/FullTest.sol"; +import { AldexRouter } from "../../../v0.8.17/AldexRouter.sol"; +import { AldexBank } from "../../../v0.8.17/AldexBank.sol"; + +contract OpenPositionWithSwapForUI is FullTest, IUserPosition { + uint256 initialTimestamp = 100; + uint16 toleranceBps = 10000; + uint256 expiredTime = 10; + uint24 tickSpacing = 1; + + IConcentratedLiquidityPoolStruct.MintParams mintParamsData; + + struct Data { + uint160 sqrtCurrentPrice; + uint160 sqrtLowerPrice; + uint160 sqrtUpperPrice; + uint256 m; + uint256 T; + uint128 amount1desired; + uint128 amount0desired; + uint256 liquidityPadded; + uint160 newPrice; + uint128 maxAusdDebt; + uint128 maxToken0ForSwap; + } + + // Calculate with known Total token0 amount (T) + // Token amount= 1 + // Lower price = 0.6000306980233852 + // Lower tick = -5108 + // Upper price = 1.0700406251956536 + // Upper tick = 677 + // Curr price = 1.0000030259411101 + // Boost = 2 + // New T = 0.8985000000000001 + // Lower * Upper = 0.8012847329442434 + // m = 1.1476604309620058 + // amount0 in position = 0.23120584040377085 + // amount1 in position = 1.5657988975971464 + // amount0 to swap = 0.7350245167952464 + // maxAusdDebt = 0.8985027188080873 + // debtRatio = 50.0 + // positionValu 1.7970054376161746 + function test_openUserPositionWithSwap_UI_dataFromPyGenerator_exactCurrentPrice_ShouldPass() + external + { + Data memory data; + + data.sqrtCurrentPrice = 7922828238405067 * 1e13; + console.log("sqrtCurrPrice ", data.sqrtCurrentPrice); + + lower["bnb0"] = -10; + upper["bnb0"] = 691; + + lower["bnb1"] = -800000; + upper["bnb1"] = 5699; + + tokenAmount["bnb0"] = 100000000000 * 1e18; + tokenAmount["bnb1"] = 1e18; + + uint256 boost = 200 * 1e16; + + data.sqrtLowerPrice = TickMath.getSqrtRatioAtTick(lower["bnb1"]); + data.sqrtUpperPrice = TickMath.getSqrtRatioAtTick(upper["bnb1"]); + + data.m = + 1e18 + + FullMath.mulDiv( + FullMath.mulDiv( + data.sqrtCurrentPrice, + data.sqrtUpperPrice - data.sqrtCurrentPrice, + data.sqrtCurrentPrice - data.sqrtLowerPrice + ), + 1e18, + data.sqrtUpperPrice + ); + + data.T = tokenAmount["bnb1"] - FullMath.mulDiv(tokenAmount["bnb1"], 8, 100); + + data.liquidityPadded = 2944919824747902675024977443088 << 96; + + data.newPrice = uint160( + UnsafeMath.divRoundingUp( + data.liquidityPadded, + data.liquidityPadded / data.sqrtCurrentPrice + data.T + ) + ); + + // y = boost * T * P * P / m + data.amount1desired = uint128( + FullMath.mulDiv( + boost, + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + data.sqrtCurrentPrice, + data.T + ), + data.m + ) + ); + + // x = (2 * T * P * P - y) / (P * P) + data.amount0desired = uint128( + FullMath.mulDiv( + FullMath.mulDiv( + 2, + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + data.sqrtCurrentPrice, + data.T + ), + 1 + ) - data.amount1desired, + 1e18, + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( + data.sqrtCurrentPrice, + 1e18 + ) + ) + ); + + console.log("m ", data.m); + console.log("T ", data.T); + console.log("amount0desired", data.amount0desired); + console.log("amount1desired", data.amount1desired); + console.log("old price ", data.sqrtCurrentPrice); + console.log("new price ", data.newPrice); + + data.T = + tokenAmount["bnb1"] - + FullMath.mulDiv(tokenAmount["bnb1"], 8, 100) - + FullMath.mulDiv(tokenAmount["bnb1"], 15, 10000); + + // D = T*P*P * (boost - 1) + data.maxAusdDebt = uint128( + FullMath.mulDiv( + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + data.newPrice, + data.T + ), + boost - 100e16, + 100e16 + ) + ); + + console.log("maxAusdDebt ", data.maxAusdDebt); + + // O = y - D # a half of overdebt - AUSD + // S = O / (P * P) # Token0 + data.maxToken0ForSwap = uint128( + FullMath.mulDiv( + data.amount1desired - data.maxAusdDebt, + 1e18, + AldexMath.ausdValueFromSqrtPriceX96xAmountE18(data.newPrice, 1e18) + ) + ); + + // S = S + S * slippage + S * swapFee + data.maxToken0ForSwap = + data.maxToken0ForSwap + + uint128(FullMath.mulDiv(data.maxToken0ForSwap, 8, 100)) + + uint128(FullMath.mulDiv(data.maxToken0ForSwap, 15, 10000)); + + console.log("maxToken0ForSw", data.maxToken0ForSwap); + + vm.warp(initialTimestamp); + assertEq(block.timestamp, initialTimestamp); + + bnb = createTokenAndDeployPoolWithPrice( + bnbOwner, + "bnb", + "BNB", + 18, + 1, + tickSpacing, + data.sqrtCurrentPrice + ); + + //prepare oracle checker + setTokenPrice(bnb, initialTimestamp); + setOracleToken(bnb, toleranceBps, expiredTime); + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb0"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb0"]); + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb0"], + lower["bnb0"], + upper["bnb0"] + ); + vm.prank(liquidityProvider1); + aldexBank.openUserPosition(bnb.pool, 6598468429376337380, mintParamsData); + + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb1"], + lower["bnb1"], + upper["bnb1"] + ); + + mintParamsData.amount0Desired = data.amount0desired; + mintParamsData.amount1Desired = data.amount1desired; + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"]); + + console.log("Balance before", bnb.token.balanceOf(liquidityProvider1)); + + vm.prank(liquidityProvider1); + aldexBank.openUserPositionWithSwap( + bnb.pool, + 1, // now minLiquidity here is 1 for simplicity. We can change this later + mintParamsData, + data.maxToken0ForSwap, // amount0 to swap + data.maxAusdDebt // MaxAusdDebt + ); + console.log("Balance after:", bnb.token.balanceOf(liquidityProvider1)); + } + + // CASE #2 + // ____________________________________ *25059____________________ initial price + // _________________|21000-------------------------30001|_________ basic position [bnb0] + // ________________________|21974----------25737|_________________ new position [bnb1] + + // Calculate with known Total token0 amount (T) + // Token amount= 100 + // Lower price = 0.8 + // Upper price = 1.1 + // Curr price = 1 + // New T = 90.0 + // Lower * Upper = 0.938083151964686 + // m = 1.44080868165941 + // amount0 in position = 55.070158660697274 + // amount1 in position = 124.92984133930273 + // amount0 to swap = 38.422825473233 + // maxAusdDebt = 90.0 + // debtRatio = 50.0 + // positionValu 180.0 + function test_openUserPositionWithSwap_UI_fromPython_ShouldPass() external { + int24 currentPrice = 0; + + lower["bnb0"] = -2228; + upper["bnb0"] = 2229; + + lower["bnb1"] = -2230; + upper["bnb1"] = 953; + + tokenAmount["bnb0"] = 10000000 * 1e18; + tokenAmount["bnb1"] = 100 * 1e18; + + // uint128 amount0desired = 61189065 * 1e12; + uint128 amount0desired = 124929841 * 1e12; + uint128 amount1desired = 124929841 * 1e12; + uint128 maxToken0ForSwap = 38422825 * 1e12; + uint128 maxAusdDebt = 90 * 1e18; + + vm.warp(initialTimestamp); + assertEq(block.timestamp, initialTimestamp); + + bnb = createTokenAndDeployPool( + bnbOwner, + "bnb", + "BNB", + 18, + 15, + tickSpacing, + currentPrice + ); + + //prepare oracle checker + setTokenPrice(bnb, initialTimestamp); + setOracleToken(bnb, toleranceBps, expiredTime); + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb0"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb0"]); + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb0"], + lower["bnb0"], + upper["bnb0"] + ); + vm.prank(liquidityProvider1); + aldexBank.openUserPosition(bnb.pool, 1, mintParamsData); + + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb1"], + lower["bnb1"], + upper["bnb1"] + ); + + mintParamsData.amount0Desired = amount0desired; + mintParamsData.amount1Desired = amount1desired; + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb1"] * 10); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb1"] * 10); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"] * 10); + + vm.prank(liquidityProvider1); + uint64 positionId = aldexBank.openUserPositionWithSwap( + bnb.pool, + 1, // now minLiquidity here is 1 for simplicity. We can change this later + mintParamsData, + maxToken0ForSwap, // amount0 to swap + maxAusdDebt // MaxAusdDebt + ); + } + + // CASE #1 + // ____________________________________ *25059____________________ initial price + // _________________|21000-------------------------30001|_________ basic position [bnb0] + // ________________________|21974----------25737|_________________ new position [bnb1] + + // Calculate with known Total token0 amount (T) + // Token amount= 1 + // Lower price = 9.0006 + // Upper price = 13.1126 + // Curr price = 12.2531 + // Boost = 1.5 + // New T = 0.9 + // Lower * Upper = 10.863759365891719 + // m = 1.233174317611736 + // amount0 in position = 0.7052642593023521 + // amount1 in position = 13.41390650434235 + // amount0 to swap = 0.7092093147674126 + // maxAusdDebt = 5.513895000000001 + // debtRatio = 25.000000000000004 + // positionValu 22.055580000000003 + function test_openUserPositionWithSwap_UI_diffBoost_ShouldPass() external { + int24 currentPrice = 25059; + uint160 sqrtCurrentPrice = TickMath.getSqrtRatioAtTick(currentPrice); + + lower["bnb0"] = 21000; + upper["bnb0"] = 30001; + + lower["bnb1"] = 21974; + upper["bnb1"] = 25737; + + tokenAmount["bnb0"] = 100000000000 * 1e18; + tokenAmount["bnb1"] = 1e18; + + uint128 amount1desired = 13413906 * 1e12; + uint128 amount0desired = uint128( + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + sqrtCurrentPrice, + amount1desired + ) + ); + + console.log(amount1desired); + console.log(amount0desired); + + uint128 maxToken0ForSwap = 709209 * 1e12; + uint128 maxAusdDebt = 5513895 * 1e12; + + vm.warp(initialTimestamp); + assertEq(block.timestamp, initialTimestamp); + + bnb = createTokenAndDeployPool( + bnbOwner, + "bnb", + "BNB", + 18, + 15, + tickSpacing, + currentPrice + ); + + //prepare oracle checker + setTokenPrice(bnb, initialTimestamp); + setOracleToken(bnb, toleranceBps, expiredTime); + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb0"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb0"]); + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb0"], + lower["bnb0"], + upper["bnb0"] + ); + vm.prank(liquidityProvider1); + aldexBank.openUserPosition(bnb.pool, 1, mintParamsData); + + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb1"], + lower["bnb1"], + upper["bnb1"] + ); + + mintParamsData.amount0Desired = amount0desired; + mintParamsData.amount1Desired = amount1desired; + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"]); + + console.log("Balance before: ", bnb.token.balanceOf(liquidityProvider1)); + + vm.prank(liquidityProvider1); + uint64 positionId = aldexBank.openUserPositionWithSwap( + bnb.pool, + 1, // now minLiquidity here is 1 for simplicity. We can change this later + mintParamsData, + maxToken0ForSwap, // amount0 to swap + maxAusdDebt // MaxAusdDebt + ); + console.log("Balance after : ", bnb.token.balanceOf(liquidityProvider1)); + + (, uint256 debtRatio, , ) = calculateTokenOutAndDebtRatioWithoutFees( + bnb, + liquidityProvider1, + positionId, + false + ); + console.log("Debt ratio: ", debtRatio); + } + + // CASE #1 + // ____________________________________ *25059____________________ initial price + // _________________|21000-------------------------30001|_________ basic position [bnb0] + // ________________________|21974----------25737|_________________ new position [bnb1] + + // Calculate with known Total token0 amount (T) + // Token amount= 1 + // Lower price = 9.0006 + // Upper price = 13.1126 + // Curr price = 12.2531 + // Boost = 1 + // New T = 0.9 + // Lower * Upper = 10.863759365891719 + // m = 1.233174317611736 + // amount0 in position = 1.0701761728682349 + // amount1 in position = 8.942604336228232 + // amount0 to swap = 0.8028062098449416 + // maxAusdDebt = 0.0 + // debtRatio = 0.0 + // positionValu 22.055580000000003 + function test_openUserPositionWithSwap_UI_zeroDebt_ShouldPass() external { + int24 currentPrice = 25059; + uint160 sqrtCurrentPrice = TickMath.getSqrtRatioAtTick(currentPrice); + + lower["bnb0"] = 21000; + upper["bnb0"] = 30001; + + lower["bnb1"] = 21974; + upper["bnb1"] = 25737; + + tokenAmount["bnb0"] = 100000000000 * 1e18; + tokenAmount["bnb1"] = 1e18; + + uint128 amount1desired = 8942604 * 1e12; + uint128 amount0desired = uint128( + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + sqrtCurrentPrice, + amount1desired + ) + ); + + console.log(amount1desired); + console.log(amount0desired); + + uint128 maxToken0ForSwap = 802806 * 1e12; + uint128 maxAusdDebt = 0; + + vm.warp(initialTimestamp); + assertEq(block.timestamp, initialTimestamp); + + bnb = createTokenAndDeployPool( + bnbOwner, + "bnb", + "BNB", + 18, + 15, + tickSpacing, + currentPrice + ); + + //prepare oracle checker + setTokenPrice(bnb, initialTimestamp); + setOracleToken(bnb, toleranceBps, expiredTime); + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb0"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb0"]); + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb0"], + lower["bnb0"], + upper["bnb0"] + ); + vm.prank(liquidityProvider1); + aldexBank.openUserPosition(bnb.pool, 1, mintParamsData); + + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb1"], + lower["bnb1"], + upper["bnb1"] + ); + + mintParamsData.amount0Desired = amount0desired; + mintParamsData.amount1Desired = amount1desired; + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"]); + + console.log("Balance before: ", bnb.token.balanceOf(liquidityProvider1)); + + vm.prank(liquidityProvider1); + uint64 positionId = aldexBank.openUserPositionWithSwap( + bnb.pool, + 1, // now minLiquidity here is 1 for simplicity. We can change this later + mintParamsData, + maxToken0ForSwap, // amount0 to swap + maxAusdDebt // MaxAusdDebt + ); + console.log("Balance after : ", bnb.token.balanceOf(liquidityProvider1)); + + (, uint256 debtRatio, , ) = calculateTokenOutAndDebtRatioWithoutFees( + bnb, + liquidityProvider1, + positionId, + false + ); + console.log("Debt ratio: ", debtRatio); + } + + // CASE WITH UPPER_ORDER + function test_openUserPositionWithSwap_upperOrder_ShouldPass() external { + Data memory data; + + int24 currentPriceTick = 25901; + data.sqrtCurrentPrice = TickMath.getSqrtRatioAtTick(currentPriceTick); + console.log("sqrtCurrentPrice", data.sqrtCurrentPrice); + + lower["bnb0"] = 25386; + upper["bnb0"] = 26577; + + lower["bnb1"] = -23028; + upper["bnb1"] = 26579; + + tokenAmount["bnb0"] = 7502 * 1e18; + tokenAmount["bnb1"] = 1 * 1e18; + + vm.warp(initialTimestamp); + assertEq(block.timestamp, initialTimestamp); + + bnb = createTokenAndDeployPool( + bnbOwner, + "bnb", + "BNB", + 18, + 1500, + tickSpacing, + currentPriceTick + ); + + // bnb = createTokenAndDeployPool2( + // bnbOwner, + // "bnb", + // "BNB", + // 18, + // 1, + // tickSpacing, + // data.sqrtCurrentPrice + // ); + + //prepare oracle checker + setTokenPrice(bnb, initialTimestamp); + setOracleToken(bnb, toleranceBps, expiredTime); + + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb0"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb0"]); + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb0"], + lower["bnb0"], + upper["bnb0"] + ); + vm.prank(liquidityProvider1); + aldexBank.openUserPosition(bnb.pool, 10647773680001070404, mintParamsData); + + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount["bnb1"], + lower["bnb1"], + upper["bnb1"] + ); + + mintParamsData.amount0Desired = data.amount0desired; + mintParamsData.amount1Desired = data.amount1desired; + } + + function _openPositionWithSwap(int24 lower, int24 upper) internal { + Data memory data; + // uint256 boost = 2; + + data.sqrtLowerPrice = TickMath.getSqrtRatioAtTick(lower); + data.sqrtUpperPrice = TickMath.getSqrtRatioAtTick(upper); + + data.m = + 1e18 + + FullMath.mulDiv( + FullMath.mulDiv( + data.sqrtCurrentPrice, + data.sqrtUpperPrice - data.sqrtCurrentPrice, + data.sqrtCurrentPrice - data.sqrtLowerPrice + ), + 1e18, + data.sqrtUpperPrice + ); + + data.T = + tokenAmount["bnb1"] - + FullMath.mulDiv(tokenAmount["bnb1"], 25, 10000); + + data.liquidityPadded = 2944919824747902675024977443088 << 96; + + data.newPrice = uint160( + UnsafeMath.divRoundingUp( + data.liquidityPadded, + data.liquidityPadded / data.sqrtCurrentPrice + data.T + ) + ); + + // y = boost * T * P * P / m + data.amount1desired = uint128( + FullMath.mulDiv( + 200 * 1e16, + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + data.sqrtCurrentPrice, + data.T + ), + data.m + ) + ); + + // amount1desired = amount1desired; + + // amount1desired = 1573422946998320480; + + // x = (2 * T * P * P - y) / (P * P) + data.amount0desired = uint128( + FullMath.mulDiv( + FullMath.mulDiv( + 2, + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + data.sqrtCurrentPrice, + data.T + ), + 1 + ) - data.amount1desired, + 1e18, + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( + data.sqrtCurrentPrice, + 1e18 + ) + ) + ); + + // amount0desired = 236736879115460192; + + console.log("m", data.m); + // console.log("m", 11476604309620058 * 1e2); + + console.log("T", data.T); + // console.log("T", 8985000000000001 * 1e2); + + console.log("amount0desired", data.amount0desired); + // console.log("amount0desired", 231205840403770850); + + console.log("amount1desired", data.amount1desired); + // console.log("amount1desired", 15657988975971464 * 1e2); + + // uint128 amount0desired = 231205840403770850; + // uint128 amount1desired = 15657988975971464 * 1e2; //17855522626850114 * 1e3; + // uint128 amount0desired = uint128( + // AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + // sqrtCurrentPrice, + // amount1desired + // ) + // ); + + console.log("old price", data.sqrtCurrentPrice); + console.log("new price", data.newPrice); + + data.T = + tokenAmount["bnb1"] - + FullMath.mulDiv(tokenAmount["bnb1"], 25, 10000) - + FullMath.mulDiv(tokenAmount["bnb1"], 1500, 10000); + + // D = T*P*P * (boost - 1) + data.maxAusdDebt = uint128( + FullMath.mulDiv( + AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + data.newPrice, + data.T + ), + 100, + 100 + ) + ); + + // data.maxAusdDebt = data.maxAusdDebt - 1e5; + // maxAusdDebt - + // uint128(FullMath.mulDiv(maxAusdDebt, 8, 100)) - + // uint128(FullMath.mulDiv(maxAusdDebt, 15, 10000)); + + console.log("maxAusdDebt", data.maxAusdDebt); + // console.log("maxAusdDebt", 8985027188080873 * 1e2); + + // O = y - D # a half of overdebt - AUSD + // S = O / (P * P) # Token0 + data.maxToken0ForSwap = uint128( + FullMath.mulDiv( + data.amount1desired - data.maxAusdDebt, + 1e18, + AldexMath.ausdValueFromSqrtPriceX96xAmountE18(data.newPrice, 1e18) + ) + ); + + // S = S + S * slippage + S * swapFee + data.maxToken0ForSwap = + data.maxToken0ForSwap + + uint128(FullMath.mulDiv(data.maxToken0ForSwap, 25, 10000)) + + uint128(FullMath.mulDiv(data.maxToken0ForSwap, 1500, 10000)); + + // maxToken0ForSwap = + // maxToken0ForSwap + + // uint128(FullMath.mulDiv(maxToken0ForSwap, 10, 100)) + + // uint128(FullMath.mulDiv(maxToken0ForSwap, 15, 10000)); + + // uint128 maxToken0ForSwap = 7350245167952464 * 1e4; //6154354957480472 * 1e2; + + console.log("maxToken0ForSwap", data.maxToken0ForSwap); + // console.log("maxToken0ForSwap", 7350245167952464 * 1e2); + + // uint128 maxAusdDebt = 8985027188080873 * 1e2; //11009410350000001 * 1e3; + vm.prank(bnbOwner); + bnb.token.mint(liquidityProvider1, tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexBank), tokenAmount["bnb1"]); + vm.prank(liquidityProvider1); + bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"]); + + console.log("lowerOld"); + console.logInt(mintParamsData.lowerOld); + console.log("upperOld"); + console.logInt(mintParamsData.upperOld); + // console.log("amount1desired ", amount1desired); + // console.log("maxToken0ForSwap", maxToken0ForSwap); + // console.log("maxAusdDebt ", maxAusdDebt); + + console.log("Balance before: ", bnb.token.balanceOf(liquidityProvider1)); + + vm.prank(liquidityProvider1); + aldexBank.openUserPositionWithSwap( + bnb.pool, + 1, // now minLiquidity here is 1 for simplicity. We can change this later + mintParamsData, + data.maxToken0ForSwap, // amount0 to swap + data.maxAusdDebt // MaxAusdDebt + ); + console.log("Balance after : ", bnb.token.balanceOf(liquidityProvider1)); + } +} From 030f56483d81b7584f804069241266763d24831a Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Wed, 5 Apr 2023 11:40:08 +0200 Subject: [PATCH 6/7] chore: refactor and improve tests --- .../AldexBank/openPositionWithSwapForUI.sol | 424 +++++++++--------- 1 file changed, 212 insertions(+), 212 deletions(-) diff --git a/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol b/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol index d6cadc1..099be10 100644 --- a/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol +++ b/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol @@ -8,6 +8,7 @@ import { IUserPosition } from "../../../v0.8.17/interfaces/IUserPosition.sol"; // libraries import { UnsafeMath } from "../../../v0.8.17/libraries/UnsafeMath.sol"; import { TickMath } from "../../../v0.8.17/libraries/TickMath.sol"; +import { DyDxMath } from "../../../v0.8.17/libraries/DyDxMath.sol"; import { FullMath } from "../../../v0.8.17/libraries/FullMath.sol"; import { AldexMath } from "../../../v0.8.17/libraries/AldexMath.sol"; // implementation @@ -32,28 +33,12 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { uint128 amount1desired; uint128 amount0desired; uint256 liquidityPadded; + uint128 minLiquidity; uint160 newPrice; uint128 maxAusdDebt; uint128 maxToken0ForSwap; } - // Calculate with known Total token0 amount (T) - // Token amount= 1 - // Lower price = 0.6000306980233852 - // Lower tick = -5108 - // Upper price = 1.0700406251956536 - // Upper tick = 677 - // Curr price = 1.0000030259411101 - // Boost = 2 - // New T = 0.8985000000000001 - // Lower * Upper = 0.8012847329442434 - // m = 1.1476604309620058 - // amount0 in position = 0.23120584040377085 - // amount1 in position = 1.5657988975971464 - // amount0 to swap = 0.7350245167952464 - // maxAusdDebt = 0.8985027188080873 - // debtRatio = 50.0 - // positionValu 1.7970054376161746 function test_openUserPositionWithSwap_UI_dataFromPyGenerator_exactCurrentPrice_ShouldPass() external { @@ -234,26 +219,9 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { console.log("Balance after:", bnb.token.balanceOf(liquidityProvider1)); } - // CASE #2 - // ____________________________________ *25059____________________ initial price - // _________________|21000-------------------------30001|_________ basic position [bnb0] - // ________________________|21974----------25737|_________________ new position [bnb1] - - // Calculate with known Total token0 amount (T) - // Token amount= 100 - // Lower price = 0.8 - // Upper price = 1.1 - // Curr price = 1 - // New T = 90.0 - // Lower * Upper = 0.938083151964686 - // m = 1.44080868165941 - // amount0 in position = 55.070158660697274 - // amount1 in position = 124.92984133930273 - // amount0 to swap = 38.422825473233 - // maxAusdDebt = 90.0 - // debtRatio = 50.0 - // positionValu 180.0 - function test_openUserPositionWithSwap_UI_fromPython_ShouldPass() external { + function test_openUserPositionWithSwap_UI_dataFromPyGenerator_asymmetricLeftRange_ShouldPass() + external + { int24 currentPrice = 0; lower["bnb0"] = -2228; @@ -328,13 +296,8 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { ); } - // CASE #1 - // ____________________________________ *25059____________________ initial price - // _________________|21000-------------------------30001|_________ basic position [bnb0] - // ________________________|21974----------25737|_________________ new position [bnb1] - // Calculate with known Total token0 amount (T) - // Token amount= 1 + // Token amount = 1 // Lower price = 9.0006 // Upper price = 13.1126 // Curr price = 12.2531 @@ -348,7 +311,9 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { // maxAusdDebt = 5.513895000000001 // debtRatio = 25.000000000000004 // positionValu 22.055580000000003 - function test_openUserPositionWithSwap_UI_diffBoost_ShouldPass() external { + function test_openUserPositionWithSwap_UI_dataFromPyGenerator_boost_1_5_ShouldPass() + external + { int24 currentPrice = 25059; uint160 sqrtCurrentPrice = TickMath.getSqrtRatioAtTick(currentPrice); @@ -443,11 +408,6 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { console.log("Debt ratio: ", debtRatio); } - // CASE #1 - // ____________________________________ *25059____________________ initial price - // _________________|21000-------------------------30001|_________ basic position [bnb0] - // ________________________|21974----------25737|_________________ new position [bnb1] - // Calculate with known Total token0 amount (T) // Token amount= 1 // Lower price = 9.0006 @@ -463,7 +423,9 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { // maxAusdDebt = 0.0 // debtRatio = 0.0 // positionValu 22.055580000000003 - function test_openUserPositionWithSwap_UI_zeroDebt_ShouldPass() external { + function test_openUserPositionWithSwap_UI_dataFromPyGenerator_zeroDebt_ShouldPass() + external + { int24 currentPrice = 25059; uint160 sqrtCurrentPrice = TickMath.getSqrtRatioAtTick(currentPrice); @@ -558,46 +520,40 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { console.log("Debt ratio: ", debtRatio); } - // CASE WITH UPPER_ORDER - function test_openUserPositionWithSwap_upperOrder_ShouldPass() external { + function test_openUserPositionWithSwap_UI_dataFromPyGenerator_asymmetricPositionBoost199_ShouldPass() + external + { Data memory data; - int24 currentPriceTick = 25901; - data.sqrtCurrentPrice = TickMath.getSqrtRatioAtTick(currentPriceTick); - console.log("sqrtCurrentPrice", data.sqrtCurrentPrice); + data.sqrtCurrentPrice = 4292715231346755932957245858477; + console.log("sqrtCurrPrice ", data.sqrtCurrentPrice); + + lower["bnb0"] = 79766; + upper["bnb0"] = 80263; - lower["bnb0"] = 25386; - upper["bnb0"] = 26577; + lower["bnb1"] = 69082; + upper["bnb1"] = 80069; - lower["bnb1"] = -23028; - upper["bnb1"] = 26579; + tokenAmount["bnb0"] = 40 * 1e18; + tokenAmount["bnb1"] = 1e18; - tokenAmount["bnb0"] = 7502 * 1e18; - tokenAmount["bnb1"] = 1 * 1e18; + uint256 boost = 150 * 1e16; + uint24 swapFee = 15; // 0.15% + uint256 slippage = 25; // 0.25% vm.warp(initialTimestamp); assertEq(block.timestamp, initialTimestamp); - bnb = createTokenAndDeployPool( + bnb = createTokenAndDeployPoolWithPrice( bnbOwner, "bnb", "BNB", 18, - 1500, + swapFee, tickSpacing, - currentPriceTick + data.sqrtCurrentPrice ); - // bnb = createTokenAndDeployPool2( - // bnbOwner, - // "bnb", - // "BNB", - // 18, - // 1, - // tickSpacing, - // data.sqrtCurrentPrice - // ); - //prepare oracle checker setTokenPrice(bnb, initialTimestamp); setOracleToken(bnb, toleranceBps, expiredTime); @@ -613,185 +569,229 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { upper["bnb0"] ); vm.prank(liquidityProvider1); - aldexBank.openUserPosition(bnb.pool, 10647773680001070404, mintParamsData); + aldexBank.openUserPosition(bnb.pool, 1, mintParamsData); + console.log("Position #0 has been opened **********************"); - mintParamsData = _prepareDataForOpenUserPosition( - bnb, - tokenAmount["bnb1"], + _openPositionWithSwap( lower["bnb1"], - upper["bnb1"] + upper["bnb1"], + tokenAmount["bnb1"], + data.sqrtCurrentPrice, + boost, + swapFee, + slippage ); - - mintParamsData.amount0Desired = data.amount0desired; - mintParamsData.amount1Desired = data.amount1desired; } - function _openPositionWithSwap(int24 lower, int24 upper) internal { + function _openPositionWithSwap( + int24 lower, + int24 upper, + uint128 tokenAmount, + uint160 sqrtCurrentPrice, + uint256 boost, + uint24 swapFee, + uint256 slippage + ) internal { Data memory data; - // uint256 boost = 2; + data.sqrtCurrentPrice = sqrtCurrentPrice; data.sqrtLowerPrice = TickMath.getSqrtRatioAtTick(lower); data.sqrtUpperPrice = TickMath.getSqrtRatioAtTick(upper); - - data.m = - 1e18 + - FullMath.mulDiv( - FullMath.mulDiv( - data.sqrtCurrentPrice, - data.sqrtUpperPrice - data.sqrtCurrentPrice, - data.sqrtCurrentPrice - data.sqrtLowerPrice - ), - 1e18, - data.sqrtUpperPrice + console.log("PRICES: *********"); + console.logInt(lower); + console.logInt(upper); + + console.log("data.sqrtLowerPrice", data.sqrtLowerPrice); + console.log("data.sqrtUpperPrice", data.sqrtUpperPrice); + console.log("data.sqrtCurrentPri", data.sqrtCurrentPrice); + if (data.sqrtUpperPrice > data.sqrtCurrentPrice) { + // ______|------------price--|_____ + + data.liquidityPadded = 106261597403049298407895 << 96; + data.newPrice = uint160( + UnsafeMath.divRoundingUp( + data.liquidityPadded, + data.liquidityPadded / data.sqrtCurrentPrice + tokenAmount + ) ); - data.T = - tokenAmount["bnb1"] - - FullMath.mulDiv(tokenAmount["bnb1"], 25, 10000); - - data.liquidityPadded = 2944919824747902675024977443088 << 96; - - data.newPrice = uint160( - UnsafeMath.divRoundingUp( - data.liquidityPadded, - data.liquidityPadded / data.sqrtCurrentPrice + data.T - ) - ); - - // y = boost * T * P * P / m - data.amount1desired = uint128( - FullMath.mulDiv( - 200 * 1e16, - AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( - data.sqrtCurrentPrice, - data.T - ), - data.m - ) - ); - - // amount1desired = amount1desired; + // m = 1 + ((U - P) / (P - L) / U / P) + data.m = + 1e18 + + FullMath.mulDiv( + FullMath.mulDiv( + data.sqrtCurrentPrice, + data.sqrtUpperPrice - data.sqrtCurrentPrice, + data.sqrtCurrentPrice - data.sqrtLowerPrice + ), + 1e18, + data.sqrtUpperPrice + ); - // amount1desired = 1573422946998320480; + data.T = tokenAmount - FullMath.mulDiv(tokenAmount, swapFee, 10000); - // x = (2 * T * P * P - y) / (P * P) - data.amount0desired = uint128( - FullMath.mulDiv( + // y = boost * T * P * P / m + data.amount1desired = uint128( FullMath.mulDiv( - 2, - AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( - data.sqrtCurrentPrice, - data.T + FullMath.mulDiv( + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( + data.sqrtCurrentPrice, + data.T + ), + boost, + 2e18 ), - 1 - ) - data.amount1desired, - 1e18, - AldexMath.ausdValueFromSqrtPriceX96xAmountE18( - data.sqrtCurrentPrice, - 1e18 + 1e18, + data.m ) - ) - ); + ); + // x = (2 * T * P * P - y) / (P * P) + data.amount0desired = uint128( + FullMath.mulDiv( + 150e16 * + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( + data.sqrtCurrentPrice, + data.T + ) - + data.amount1desired, + 1, + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( + data.sqrtCurrentPrice, + 1e18 + ) + ) + ); + console.log("m", data.m); + console.log("T", data.T); + console.log("amount0desired", data.amount0desired); + console.log("amount1desired", data.amount1desired); - // amount0desired = 236736879115460192; + console.log("old price", data.sqrtCurrentPrice); + console.log("new price", data.newPrice); - console.log("m", data.m); - // console.log("m", 11476604309620058 * 1e2); + data.T = + tokenAmount - + FullMath.mulDiv(tokenAmount, slippage, 10000) - + FullMath.mulDiv(tokenAmount, swapFee, 10000); - console.log("T", data.T); - // console.log("T", 8985000000000001 * 1e2); + // D = T*P*P * (boost - 1) + data.maxAusdDebt = uint128( + FullMath.mulDiv( + AldexMath.ausdValueFromSqrtPriceX96xAmountE18(data.newPrice, data.T), + boost - 1e18, + boost + ) + ); - console.log("amount0desired", data.amount0desired); - // console.log("amount0desired", 231205840403770850); + console.log("maxAusdDebt ", data.maxAusdDebt); - console.log("amount1desired", data.amount1desired); - // console.log("amount1desired", 15657988975971464 * 1e2); + // O = y - D # a half of overdebt - AUSD + // S = O / (P * P) # Token0 + data.maxToken0ForSwap = uint128( + FullMath.mulDiv( + data.amount1desired - data.maxAusdDebt, + 1e18, + AldexMath.ausdValueFromSqrtPriceX96xAmountE18(data.newPrice, 1e18) + ) + ); + // S = S + S * slippage + S * swapFee + data.maxToken0ForSwap = + data.maxToken0ForSwap + + uint128(FullMath.mulDiv(data.maxToken0ForSwap, slippage, 10000)) + + uint128(FullMath.mulDiv(data.maxToken0ForSwap, swapFee, 10000)); + + console.log("maxToken0ForSw", data.maxToken0ForSwap); + } else { + console.log("Range to the left of the price"); + // _____|-------|__price____ + data.amount0desired = uint128( + tokenAmount - FullMath.mulDiv(tokenAmount, uint256(swapFee), 10000) + ); - // uint128 amount0desired = 231205840403770850; - // uint128 amount1desired = 15657988975971464 * 1e2; //17855522626850114 * 1e3; - // uint128 amount0desired = uint128( - // AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( - // sqrtCurrentPrice, - // amount1desired - // ) - // ); + data.liquidityPadded = 106261597403049298407895 << 96; + data.newPrice = uint160( + UnsafeMath.divRoundingUp( + data.liquidityPadded, + data.liquidityPadded / data.sqrtCurrentPrice + tokenAmount + ) + ); - console.log("old price", data.sqrtCurrentPrice); - console.log("new price", data.newPrice); + console.log("old price", data.sqrtCurrentPrice); + console.log("new price", data.newPrice); - data.T = - tokenAmount["bnb1"] - - FullMath.mulDiv(tokenAmount["bnb1"], 25, 10000) - - FullMath.mulDiv(tokenAmount["bnb1"], 1500, 10000); + data.amount1desired = uint128( + 2 * + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( + data.newPrice, + data.amount0desired + ) + ); // 2 * tokenValue - // D = T*P*P * (boost - 1) - data.maxAusdDebt = uint128( - FullMath.mulDiv( - AldexMath.tokenValueFromSqrtPriceX96xAusdAmountE18( + console.log("amount0desired ", data.amount0desired); + console.log("amount1desired ", data.amount1desired); + + data.maxAusdDebt = uint128( + AldexMath.ausdValueFromSqrtPriceX96xAmountE18( data.newPrice, - data.T - ), - 100, - 100 + data.amount0desired + ) - 10 + ); // tokenValue + + data.amount0desired = 0; + + console.log("maxAusdDebt ", data.maxAusdDebt); + data.maxToken0ForSwap = tokenAmount; + console.log("maxToken0ForSwap", data.maxToken0ForSwap); + + console.log("sqrtCurrentPrice", data.sqrtCurrentPrice); + console.log("sqrtLowerPrice ", data.sqrtLowerPrice); + console.log("sqrtUpperPrice ", data.sqrtUpperPrice); + + data.minLiquidity = uint128( + DyDxMath.getLiquidityForAmounts( + uint256(data.sqrtLowerPrice), + uint256(data.sqrtUpperPrice), + uint256(data.sqrtCurrentPrice), + uint256(data.amount1desired), + uint256(data.amount0desired) + ) + ); + console.log("minLiquidity ", data.minLiquidity); + } + + data.minLiquidity = uint128( + DyDxMath.getLiquidityForAmounts( + uint256(data.sqrtLowerPrice), + uint256(data.sqrtUpperPrice), + uint256(data.sqrtCurrentPrice), + uint256(data.amount1desired), + uint256(data.amount0desired) ) ); - // data.maxAusdDebt = data.maxAusdDebt - 1e5; - // maxAusdDebt - - // uint128(FullMath.mulDiv(maxAusdDebt, 8, 100)) - - // uint128(FullMath.mulDiv(maxAusdDebt, 15, 10000)); - - console.log("maxAusdDebt", data.maxAusdDebt); - // console.log("maxAusdDebt", 8985027188080873 * 1e2); - - // O = y - D # a half of overdebt - AUSD - // S = O / (P * P) # Token0 - data.maxToken0ForSwap = uint128( - FullMath.mulDiv( - data.amount1desired - data.maxAusdDebt, - 1e18, - AldexMath.ausdValueFromSqrtPriceX96xAmountE18(data.newPrice, 1e18) - ) + mintParamsData = _prepareDataForOpenUserPosition( + bnb, + tokenAmount, + lower, + upper ); - // S = S + S * slippage + S * swapFee - data.maxToken0ForSwap = - data.maxToken0ForSwap + - uint128(FullMath.mulDiv(data.maxToken0ForSwap, 25, 10000)) + - uint128(FullMath.mulDiv(data.maxToken0ForSwap, 1500, 10000)); - - // maxToken0ForSwap = - // maxToken0ForSwap + - // uint128(FullMath.mulDiv(maxToken0ForSwap, 10, 100)) + - // uint128(FullMath.mulDiv(maxToken0ForSwap, 15, 10000)); - - // uint128 maxToken0ForSwap = 7350245167952464 * 1e4; //6154354957480472 * 1e2; - - console.log("maxToken0ForSwap", data.maxToken0ForSwap); - // console.log("maxToken0ForSwap", 7350245167952464 * 1e2); + mintParamsData.amount0Desired = data.amount0desired; + mintParamsData.amount1Desired = data.amount1desired; - // uint128 maxAusdDebt = 8985027188080873 * 1e2; //11009410350000001 * 1e3; vm.prank(bnbOwner); - bnb.token.mint(liquidityProvider1, tokenAmount["bnb1"]); + bnb.token.mint(liquidityProvider1, tokenAmount); vm.prank(liquidityProvider1); - bnb.token.approve(address(aldexBank), tokenAmount["bnb1"]); + bnb.token.approve(address(aldexBank), tokenAmount); vm.prank(liquidityProvider1); - bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"]); - - console.log("lowerOld"); - console.logInt(mintParamsData.lowerOld); - console.log("upperOld"); - console.logInt(mintParamsData.upperOld); - // console.log("amount1desired ", amount1desired); - // console.log("maxToken0ForSwap", maxToken0ForSwap); - // console.log("maxAusdDebt ", maxAusdDebt); + bnb.token.approve(address(aldexRouter), tokenAmount); console.log("Balance before: ", bnb.token.balanceOf(liquidityProvider1)); vm.prank(liquidityProvider1); aldexBank.openUserPositionWithSwap( bnb.pool, - 1, // now minLiquidity here is 1 for simplicity. We can change this later + data.minLiquidity, // now minLiquidity here is 1 for simplicity. We can change this later mintParamsData, data.maxToken0ForSwap, // amount0 to swap data.maxAusdDebt // MaxAusdDebt From 3b42283ec1df5094a449009ad6ada05bdfb5ef19 Mon Sep 17 00:00:00 2001 From: Pterygopalatinus Date: Wed, 5 Apr 2023 11:52:05 +0200 Subject: [PATCH 7/7] chore: removes unused var --- contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol b/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol index 099be10..504e227 100644 --- a/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol +++ b/contracts/tests/unit/AldexBank/openPositionWithSwapForUI.sol @@ -287,7 +287,7 @@ contract OpenPositionWithSwapForUI is FullTest, IUserPosition { bnb.token.approve(address(aldexRouter), tokenAmount["bnb1"] * 10); vm.prank(liquidityProvider1); - uint64 positionId = aldexBank.openUserPositionWithSwap( + aldexBank.openUserPositionWithSwap( bnb.pool, 1, // now minLiquidity here is 1 for simplicity. We can change this later mintParamsData,