KyberSwap Docs
  • Introduction to KyberSwap
  • Getting Started
    • Quickstart
      • FAQ
    • Supported Exchanges And Networks
    • Foundational Topics
      • Decentralized Finance
        • Tokens
        • Stablecoins
        • DEX/DeFi Aggregator
        • Slippage
        • Price Impact
        • Zap
        • Maximal Extractable Value (MEV)
      • Decentralized Technologies
        • Wallets
        • Dapps
        • RPC
        • Oracles
        • On-Chain vs Off-Chain Data
      • Other Valuable Resources
  • KyberSwap Solutions
    • KyberSwap Interface
      • User Guides
        • Connect Your Wallet
        • Switching Networks
        • Instantly Swap At Superior Rates
        • Swap At Your Preferred Rates
        • Cross-chain Swap
        • Add Your Favourite Tokens
        • Get Crypto With Fiat
        • Bridge Your Assets Across Multiple Chains
      • Profiles
        • Profile Creation
        • Profile Customization
        • Sync Profile Across Devices
      • Notifications
        • Notification Center
    • KyberSwap Aggregator
      • Concepts
        • Dynamic Trade Routing
      • User Guides
        • Instantly Swap At Superior Rates
      • Developer Guides
        • Execute A Swap With The Aggregator API
        • Upgrading To APIv1
      • Aggregator API Specification
        • EVM Swaps
        • Permit
      • Contracts
        • Aggregator Contract Addresses
      • DEX IDs
      • Subgraphs
      • FAQ
    • KyberSwap Zap as a Service
      • KyberSwap Zap as a Service (ZaaS) API
        • ZaaS HTTP API
        • ZaaS GRPC API
      • KyberSwap Zap Liquidity Widget
      • Zap Fee Model
      • Zap's Supported Chains/Dexes
      • Zap's Deployed Contract Addresses
      • Zap's DEX IDs
    • KyberSwap Widget
      • Developer Guides
        • Integrating The KyberSwap Widget
        • Customizing The KyberSwap Widget
      • iFrame Alternative
      • Widget/iFrame Fee
    • KyberSwap Liquidity Widget
      • Integrating The KyberSwap Liquidity Widget
    • Limit Order
      • Concepts
        • Off-Chain Relay, On-Chain Settlement
        • Gasless Cancellation
      • User Guides
        • Swap At Your Preferred Rates
        • Update Limit Orders
        • Cancel Limit Orders
      • Developer Guides
        • Create Limit Order
        • Gasless Cancel
        • Hard Cancel
        • Fill Limit Order
      • Contracts
        • Limit Order Contract Addresses
      • Limit Order API Specification
        • General APIs
        • Maker APIs
        • Taker APIs
      • FAQ
    • KyberSwap OnChain Price Service
    • Fee Schedule
  • Governance
    • KyberDAO
      • User Guides
        • Participating in KyberDAO
        • Staking
        • Voting
        • Stake KNC And Enjoy Gas Savings
      • Fees to KyberDAO
      • KyberDAO Operator MultiSig
      • Contracts
        • KyberDAO Contract Repo
        • KyberDAO Contract Addresses
      • FAQ - Others
    • KNC Token
      • KNC Tokenomics & Utility
      • Gas Refund Program
      • KNC Contract Addresses
  • Security
    • Audits
  • Reference
    • Legacy
      • KyberSwap Classic
        • Concepts
          • Programmable Pricing Curves
          • Dynamic Auto-Adjusting Fees
          • Virtual Balances
          • Protocol Fees
        • Contracts
          • Classic Contract Repo
          • Classic Contract Addresses
          • Classic Contract Farming Addresses
      • KyberSwap Elastic
        • Concepts
          • Concentrated Liquidity
          • Reinvestment Curve
          • Tick-Range Mechanism
          • Pool Process Flows
          • Anti-Sniping Mechanism
          • Tick-Based Farming
          • Elastic Zap
          • TWAP Oracle
          • Elastic APR Calculations
        • Contracts
          • Elastic Contract Repo
          • Elastic Contract Addresses
          • Elastic Farming Contract Addresses
          • Elastic Zap Contract Addresses
          • Elastic Core Contracts
          • Elastic Core Libraries
          • Elastic Periphery Core Contracts
          • Elastic Peripheral Library Contracts
          • Elastic Peripheral Base Contracts
        • Subgraphs
      • Whitepapers
      • Audits
      • KyberAI
        • KyberScore
        • Concepts
        • On-Chain Indicators
          • Number Of Trades
          • Trading Volume
          • Netflow To Whale Wallets
          • Netflow To CEX
          • Number Of Transfers
          • Volume Of Transfers
          • Number Of Holders
          • Top Holders
        • Technical Indicators
          • Live Charts
          • Support & Resistance Levels
          • Live Trades
          • Funding Rate On CEX
          • Liquidations On CEX
        • Liquidity Analysis
      • Elastic Legacy
        • Elastic Legacy Contract Repo
        • Elastic Legacy Contract Addresses
        • Elastic Legacy Farming Contract Addresses
        • Remove Elastic Legacy Liquidity
      • Protocol
        • Overview
        • Smart Contract Architecture
        • Trust and Security Model
      • Integrations
        • Getting Started
        • Use Cases
        • Integration Types
        • Smart Contracts
        • Ethers JS
        • RESTful API
        • Slippage Rate Protection
        • Price Feed Security
        • Contract Events
        • Platform Fees
      • Reserves
        • Getting Started
          • Overview
          • Why Develop On Kyber
          • Create New Reserve
          • Existing Reserves
          • Customising Existing Reserves
        • Development Guides
          • Fed Price Reserve
          • Automated Price Reserve
          • Reserves with Ganache
          • Orderbook Reserve
        • Operations
          • Listing Policies
          • Reserve IDs
          • Reserve Rebates
          • Sanity Rates
      • Addresses
        • Introduction
        • Mainnet
        • Kovan
        • Rinkeby
        • Ropsten
      • API/ABI
        • Introduction
        • RESTful API
          • RESTful API Overview
          • RESTful API
        • Core Smart Contracts
          • IKyberNetworkProxy
          • KyberNetworkProxy
          • IKyberNetwork
          • ISimpleKyberProxy
          • IKyberMatchingEngine
          • KyberMatchingEngine
          • IKyberHint
          • KyberHintHandler
          • IKyberHintHandler
          • IKyberFeeHandler
          • IKyberStaking
          • KyberStaking
          • IKyberDao
          • KyberDao
          • IKyberStorage
          • KyberStorage
          • IKyberHistory
          • KyberHistory
          • IKyberReserve
          • KyberReserve
          • ConversionRates
          • LiquidityConversionRates
          • EpochUtils
          • IEpochUtils
          • KyberFeeHandler
        • Contract ABIs
          • ABIs
        • Code Snippets
          • Token Quantity Conversion
        • Misc Contracts
          • KyberNetwork
          • ConversionRatesInterface
          • PermissionGroups
          • SanityRates
          • Withdrawable
          • OrderbookReserveInterface
          • OrderbookReserveLister
    • KyberSwap Operator MultiSig
    • Permitable Tokens
    • Third-Party Integrations
    • KyberSwap Analytics
    • KyberSwap App
    • GitHub
    • KyberSwap Analytics
    • KyberSwap Blog
    • Kyber Network Press Kit
  • Socials
    • X
    • Discord
    • Telegram
    • LinkedIn
    • Reddit
    • Instagram
    • Tik Tok
  • Support
    • KyberSwap Help Center
    • Complaints Handling Process
Powered by GitBook
On this page
  • Pool unlocking/initialization​
  • Overview​
  • Minting and burning (add/remove liquidity)​
  • Overview​
  • Swap
  • Overview​
  • Swapping formula​

Was this helpful?

  1. Reference
  2. Legacy
  3. KyberSwap Elastic
  4. Concepts

Pool Process Flows

Automating Tried And Tested Procedures

PreviousTick-Range MechanismNextAnti-Sniping Mechanism

Last updated 1 year ago

Was this helpful?

Pool unlocking/initialization

Overview

No action (minting / burning / swaps) can be performed prior to pool initialization.

In addition to setting the initial sqrt price, a small amount of token0 and token1 is required to be seeded for the initialization of reinvestL to the value of MIN_LIQUIDITY. This is required to prevent division by zero in the calcRMintQty() function when swaps are performed. MIN_LIQUIDITY was chosen to be reasonably small enough to avoid calculation inaccuracies for swaps, and from taking unreasonably large capital amounts from the caller.

As part of this anti-spam feature, Elastic allocates 10510^5105 token weis as liquidity for the reinvestment curve. While this amount has been carefully selected to suit the majority of tokens, there are rare exceptions where token teams decide to implement tokens with less decimals for reasons of their own. For reference, the majority of ERC20 tokens (LINK, MATIC, ANKR, SHIB, etc.) are created with 101810^{18}1018 decimals, WBTC has 10810^8108 decimals, major stablecoin tokens like USDC/USDT have 10610^6106 decimals.

In cases where the token has a low decimal value and the per unit value of the token high, the amount taken might be of significant value (i.e. a token is created with 10210^2102 decimals and each unit has a 1USD value, which results in 10510^5105 tokens with a value of 100USD being taken as an anti-spam feature). As a permissionless platform, KyberSwap supports the listing of all tokens which meet the ERC20 standard and as such, users are responsible for checking if their token falls into the aforementioned category.

Minting and burning (add/remove liquidity)

Overview

Adding and removing liquidity have very similar flows. One of the main differences is that mint() is possibly a permissioned function, but burn() is not. More information relating to the requirement for this can be found in on whitelisting position managers.

Implementation details

  • A simple check is performed to ensure that the requested liquidity amount to mint / burn is non-zero

  • _tweakPosition() is called, which does the following:

    • Load the pool state into memory poolData (current price, tick and liquidity values)

    • Call _syncFeeGrowth() to update fee growth data. Mints reinvestment tokens if necessary

    • Call _syncSecondsPerLiquidity() to update seconds per liquidity data

    • The updated global values and poolData is passed into _updatePosition()

      • Updates (initializes) the lower and upper position ticks. Will insert or remove the tick from the linked list whenever necessary

      • Calculates feeGrowthInside and returns the amount of reinvestment tokens claimable by the position

    • Transfers the claimable reinvestment tokens to the position owner, if any

    • Calculates the token0 and token1 quantity required to be collected from (add liquidity) or sent to (remove liquidity) msg.sender. Will apply liquidity changes to pool liquidity if the specified position is active

  • In the case of adding liquidity, a callback is made to collect the tokens

  • Emit event

Swap

Like KyberSwap Classic, there are 4 different types of swaps available that a user can specify.

  1. Swap from a specified amount of token 0 (exactInput0)

  2. Swap from a specified amount of token 1 (exactInput1)

  3. Swap to a specified amount of token 0 (exactOutput0)

  4. Swap to a specified amount of token 1 (exactOutput1)

Swapping token 0 for token 1 (cases 1 and 4) cause the pool price and tick to move downwards, while swapping token 1 for token 0 (cases 2 and 3) cause the pool price and tick to move upwards.

In addition, the user can specify a price limit that the swap can reach. The minimum and maximum price limits a user can specify is MIN_SQRT_RATIO + 1 and MAX_SQRT_RATIO - 1.

The algorithm exits when either the specified amount has been fully used, or if the price limit has been reached.

The swap amount is a int256 to implicitly suggest whether it is exact input (> 0) or exact output (< 0).

  1. Fetch the initial pool state

    • Lbase​L_{base​}Lbase​​ := pool.baseL (liquidity provided by positions)

    • Lreinvest​L_{reinvest​}Lreinvest​​ := pool.reinvestL (liquidity from fees collected)

    • Pcurrent\sqrt{P_{current}}Pcurrent​​ := pool.sqrtP (current sqrt price of token1/token0)

    • tct_ctc​ := pool.currentTick (tick associated with pool price)

    • tnt_ntn​ := pool.nextTick (next initialized tick from current tick)

  2. Verify specified price limit Plim\sqrt{P_{lim}}Plim​​

    • Cases 1 & 4: MIN_SQRT_RATIO < Plim\sqrt{P_{lim}}Plim​​ < Pcurrent\sqrt{P_{current}}Pcurrent​​

    • Cases 2 & 3: Pcurrent\sqrt{P_{current}}Pcurrent​​ < Plim\sqrt{P_{lim}}Plim​​ < MAX_SQRT_RATIO

  3. While specified amount deltaremainingdelta_{remaining}deltaremaining​ not used up or price limit not reached,

    • Calculate temp next tick ttmpt_{tmp}ttmp​ and next sqrt price Pnext\sqrt{P_{next}}Pnext​​. The temporary next tick is to ensure that the next tick does not exceed the MAX_TICK_DISTANCE cap from the current tick, so as not to violate the 5% price difference requirement.

      • Pnext\sqrt{P_{next}}Pnext​​ = TickMath.getSqrtRatioAtTick(ttmpt_{tmp}ttmp​)

    • Check if Pnext\sqrt{P_{next}}Pnext​​ exceeds Plim\sqrt{P_{lim}}Plim​​,

      • If true then Ptarget\sqrt{P_{target}}Ptarget​​ = Plim\sqrt{P_{lim}}Plim​​

      • If false then Ptarget\sqrt{P_{target}}Ptarget​​ = Pnext\sqrt{P_{next}}Pnext​​

    • Call SwapMath.computeSwapStep() to calculate the actual swap input and output amounts to be used, swap fee amount and next pool price

      • Subtract amount to be used (usedAmount) to swapData.specifiedAmount

      • Add amount to be sent to user (returnedAmount) to swapData.returnedAmount

      • Add collected swap fee ΔL\Delta{L}ΔL to LreinvestL_{reinvest}Lreinvest​

    • Check if swap will reach next tick

      • If true, set swapData.currentTick = willUpTick ? tempNextTick : tempNextTick - 1 and continue

      • If false, recalculate the current tick based on current price and break the loop

    • If ttmpt_{tmp}ttmp​ == tnt_ntn​, we are crossing tick tnt_ntn​:

      • Load variables (if not loaded already) that are initialized when crossing ticks

      • Calculate amount of reinvestment tokens to be minted for fees to be sent to government and to for LP contributions, and update feeGrowthGlobal

      • Cross tick tnt_ntn​: updates the tick outside values and apply tick.liquidityNet to pool liquidity whilst fetching the next tick tnt_ntn​

  4. Perform actual minting of reinvestment tokens if necessary

  5. Update pool state (price, ticks, liquidity, feeGrowth, reinvestment variables)

  6. Send token to caller, execute swap callback to collect token

    • Negative quantity = transfer to caller

    • Positive quantity = collect from caller

Field
Type
Explanation

liquidity

uint256

active base liquidity + reinvestment liquidity

currentSqrtP

uint160

current sqrt price

targetSqrtP

uint160

sqrt price limit nextSqrtP can take

feeInBps

uint256

swap fee in basis points

specifiedAmount

int256

amount remaining to be used for the swap

isExactInput

bool

true if specifiedAmount refers to input amount, false if specifiedAmount refers to output amount

isToken0

bool

true if specifiedAmount is in token0, false if specifiedAmount is in token1

Field
Type
Explanation

usedAmount

int256

actual amount to be used for the swap. >= 0 if isExactInput = true, <= 0 if isExactInput = false

returnedAmount

int256

output qty (<= 0) to be accumulated if isExactInput = true, input qty (>= 0) if isExactInput = false

deltaL

uint256

collected swap fee, to be incremented to reinvest liquidity

nextSqrtP

uint160

new sqrt price after the computed swap step

  1. Calculate the amount required to reach targetSqrtP from currentSqrtP by calling calcReachAmount().

  2. If amount required exceeds specifiedAmount, then the targetPrice will not be reached, and we expect the resulting price nextSqrtP to not exceed targetSqrtP.

    • usedAmount := specifiedAmount

    • Estimate ΔL\Delta{L}ΔL, the swap fee to be collected by calling estimateIncrementalLiquidity()

    • Calculate the final price nextSqrtP by calling calcFinalPrice()

  3. Otherwise, the temporary next tick will be crossed.

    • usedAmount will be the amount calculated in step 1

    • calculate ΔL\Delta{L}ΔL by calling calcIncrementalLiquidity()

    • set the resulting price nextSqrtP = targetSqrtP

  4. Finally, calculate returnedAmount by calling calcReturnedAmount().

Assume that:

  • x1, x2: the amount of token0 before/after swap

  • y1, y2: the amount of token1 before/after swap

  • L1, L2: the liquidity before/after swap

  • p1, p2: the price before/after swap

  • Given L1, p1, fee and Δy\Delta yΔy, calculate ΔL\Delta LΔL and p2

ΔL=L1∗Δy∗fee2∗y1\Delta L = {L_1 * {\Large {\Delta y * fee \over 2 * y1}}}ΔL=L1​∗2∗y1Δy∗fee​(1)

ΔL=Δy∗fee2∗p1\Delta L = {\Large {\Delta y * fee \over 2 * \sqrt p_1}}ΔL=2∗p​1​Δy∗fee​

Finally calculate new p2\sqrt{p_2}p2​​

p2=y1+ΔyL2\sqrt{p_2} = \Large {y_1 + \Delta y \over L_2}p2​​=L2​y1​+Δy​ (2)

p2=L1∗p1+ΔyL1+ΔL\sqrt{p_2} = \Large {L1 * \sqrt p1 + \Delta y \over L1 + \Delta L}p2​​=L1+ΔLL1∗p​1+Δy​

  • Given L1, p1 and p2 calculate the ΔL\Delta LΔL and Δy\Delta yΔy

From (2) we have:p2∗(L1+Δx∗p1)=p1∗(L1+ΔL)\sqrt p_2 * (L1 + \Delta x * \sqrt p_1) = \sqrt p_1 * (L1 + \Delta L)p​2​∗(L1+Δx∗p​1​)=p​1​∗(L1+ΔL) combine with (1)

2∗p2∗(L1+Δx∗p1)=p1∗(2∗L1+Δx∗fee∗p12 * \sqrt p_2 * (L1 + \Delta x * \sqrt p_1) = \sqrt p_1 * ( 2 * L1 + \Delta x * fee * \sqrt p_12∗p​2​∗(L1+Δx∗p​1​)=p​1​∗(2∗L1+Δx∗fee∗p​1​

=> Δx∗p1∗(2∗p2−fee∗p1)=2∗L1∗(p1−p2)\Delta x * \sqrt p1 * (2 * \sqrt p_2 - fee * \sqrt p_1) = 2 * L1 * (\sqrt p_1 - \sqrt p_2)Δx∗p​1∗(2∗p​2​−fee∗p​1​)=2∗L1∗(p​1​−p​2​)

=> (3) Δx=2∗L1∗(p1−p2)p1∗(2∗p2−fee∗p1)\Delta x = \Large {\frac{2 * L1 * (\sqrt p_1 - \sqrt p_2)}{\sqrt p_1 * (2 * \sqrt p_2 - fee * \sqrt p_1)} }Δx=p​1​∗(2∗p​2​−fee∗p​1​)2∗L1∗(p​1​−p​2​)​

  • Given L1, p1, fee and Δy\Delta yΔy, calculate ΔL\Delta LΔL and p2

ΔL=L1∗Δy∗fee2∗y1\Delta L = {L_1 * {\Large {\Delta y * fee \over 2 * y1}}}ΔL=L1​∗2∗y1Δy∗fee​(1)

ΔL=Δy∗fee2∗p1\Delta L = {\Large {\Delta y * fee \over 2 * \sqrt p_1}}ΔL=2∗p​1​Δy∗fee​

Finally calculate new p2\sqrt{p_2}p2​​

p2=y1+ΔyL2\sqrt{p_2} = \Large {y_1 + \Delta y \over L_2}p2​​=L2​y1​+Δy​(2)

p2=L1∗p1+ΔyL1+ΔL\sqrt{p_2} = \Large {L1 * \sqrt p1 + \Delta y \over L1 + \Delta L}p2​​=L1+ΔLL1∗p​1+Δy​

  • Given L1, p1 and p2 calculate the ΔL\Delta LΔL and Δy\Delta yΔy

From (1) and (2) p2∗(L1+Δy∗fee2∗p1)=L1∗p1+Δy\sqrt p_2 * (L1 + {\Large {\Delta y * fee \over 2 * \sqrt p_1}}) = L1 * \sqrt p1 + \Delta yp​2​∗(L1+2∗p​1​Δy∗fee​)=L1∗p​1+Δy

=> Δy∗(2∗p1−fee∗p2)=2∗p1∗L1∗(p2−p1)\Delta y * (2 * \sqrt p_1 - fee * \sqrt p_2) = 2 * \sqrt p_1 * L1 * (\sqrt p_2 - \sqrt p_1)Δy∗(2∗p​1​−fee∗p​2​)=2∗p​1​∗L1∗(p​2​−p​1​)

=> (3) Δy=2∗p1∗L1∗(p2−p1)(2∗p1−fee∗p2)\Delta y = \Large {2 * \sqrt p_1 * L1 * (\sqrt p_2 - \sqrt p_1) \over (2 * \sqrt p_1 - fee * \sqrt p_2)}Δy=(2∗p​1​−fee∗p​2​)2∗p​1​∗L1∗(p​2​−p​1​)​

  • Given L1, p1 and p2, calculate the Δy\Delta yΔy

y1−Δy=L2∗p2y1 - \Delta y = L2 * \sqrt p_2y1−Δy=L2∗p​2​

=> Δy=ΔL∗p2+L1∗(p2−p1)\Delta y = \Delta L * \sqrt p_2 + L1 * (\sqrt p_2 - \sqrt p_1)Δy=ΔL∗p​2​+L1∗(p​2​−p​1​)

=> Δy=Δx∗fee∗p12∗p2+L1∗(p2−p1)\Delta y = {\Large \frac{\Delta x * fee * \sqrt p_1}{2}} * \sqrt p_2 + L1 * (\sqrt p_2 - \sqrt p_1)Δy=2Δx∗fee∗p​1​​∗p​2​+L1∗(p​2​−p​1​)

=> Δy=fee∗p1∗L1∗(p1−p2)p1∗(2∗p2−fee∗p1)∗p2+L1∗(p2−p1)\Delta y = {\Large \frac{fee * \sqrt p_1 * L1 * (\sqrt p_1 - \sqrt p_2)}{\sqrt p_1 * (2 * \sqrt p_2 - fee * \sqrt p_1)}} * \sqrt p_2 + L1 * (\sqrt p_2 - \sqrt p_1)Δy=p​1​∗(2∗p​2​−fee∗p​1​)fee∗p​1​∗L1∗(p​1​−p​2​)​∗p​2​+L1∗(p​2​−p​1​)

=> Δy=L1(p1−p2)(2∗p2−fee∗p1−fee∗p2)2∗p2−fee∗p1\Delta y = {\Large \frac{L1 (\sqrt p_1 - \sqrt p_2) (2 * \sqrt p_2 - fee * \sqrt p_1 - fee * \sqrt p_2)}{2 * \sqrt p_2 - fee * \sqrt p_1}}Δy=2∗p​2​−fee∗p​1​L1(p​1​−p​2​)(2∗p​2​−fee∗p​1​−fee∗p​2​)​

  • Given L1, p1 and Δy\Delta yΔy, calculate ΔL\Delta LΔL

(L1+ΔL)2=(y1−Δy)∗(x1+Δx)(L1 + \Delta L)^2 = (y1 - \Delta y) * (x1 + \Delta x)(L1+ΔL)2=(y1−Δy)∗(x1+Δx)

=> (L1+ΔL)2=(y1−Δy)∗(x1+2∗ΔLp1∗fee)(L1 + \Delta L)^2 = (y1 - \Delta y) * (x1 + {\Large \frac{2 * \Delta L}{\sqrt p_1 * fee}})(L1+ΔL)2=(y1−Δy)∗(x1+p​1​∗fee2∗ΔL​)

=> (L1+ΔL)2∗fee=L12∗fee−fee∗Δy∗L1/p1+2∗ΔLp1∗(L1/p1−Δy)(L1 + \Delta L)^2 * fee = L1^2 * fee - fee * \Delta y * L1 / \sqrt p_1 + {\Large \frac{2 * \Delta L}{\sqrt p_1}} * (L1 / \sqrt p_1 - \Delta y)(L1+ΔL)2∗fee=L12∗fee−fee∗Δy∗L1/p​1​+p​1​2∗ΔL​∗(L1/p​1​−Δy)

=> fee∗ΔL2−2∗(L1−fee∗L1−Δy/p1)∗ΔL+L1∗fee∗Δy/p1=0fee * \Delta L^2 - 2 * (L1 - fee * L1 - \Delta y / \sqrt p_1) * \Delta L + L1 * fee * \Delta y / \sqrt p_1 = 0fee∗ΔL2−2∗(L1−fee∗L1−Δy/p​1​)∗ΔL+L1∗fee∗Δy/p​1​=0

This can be transformed into

a∗ΔL2−2∗b∗ΔL+c=0a * \Delta L ^2 - 2 * b * \Delta L + c = 0a∗ΔL2−2∗b∗ΔL+c=0

ΔL\Delta LΔL will be the smaller solution of this equation

  • Given L1, p1 and p2, calculate the Δx\Delta xΔx

x1−Δx=L2/p2x1 - \Delta x = L2 / \sqrt p_2x1−Δx=L2/p​2​

=> Δx=L1p1−ΔLp2−L1p2\Delta x = {\Large \frac{L1}{\sqrt p_1} - \frac{\Delta L}{\sqrt p_2} - \frac{L1}{\sqrt p_2}}Δx=p​1​L1​−p​2​ΔL​−p​2​L1​

=> Δx=L1p1−L1p2−Δy∗fee2∗p1∗p2\Delta x = {\Large \frac{L1}{\sqrt p_1} - \frac{L1}{\sqrt p_2} - \frac{\Delta y * fee}{ 2 * \sqrt p_1 * \sqrt p_2}}Δx=p​1​L1​−p​2​L1​−2∗p​1​∗p​2​Δy∗fee​

=> Δx=L1p1−L1p2−2∗p1∗L1∗(p2−p1)(2∗p1−fee∗p2)∗fee2∗p1∗p2\Delta x = {\Large \frac{L1}{\sqrt p_1} - \frac{L1}{\sqrt p_2} - {2 * \sqrt p_1 * L1 * (\sqrt p_2 - \sqrt p_1) \over (2 * \sqrt p_1 - fee * \sqrt p_2)} * \frac{fee}{2 * \sqrt p_1 * \sqrt p_2}}Δx=p​1​L1​−p​2​L1​−(2∗p​1​−fee∗p​2​)2∗p​1​∗L1∗(p​2​−p​1​)​∗2∗p​1​∗p​2​fee​

=> Δx=L1∗(p2−p1)p2∗p1∗(1−fee∗p12∗p1−fee∗p2)\Delta x = {\Large \frac{L1 * (\sqrt p_2 - \sqrt p_1)}{\sqrt p_2 * \sqrt p_1} * (1 - \frac{fee * \sqrt p_1}{2 * \sqrt p_1 - fee * \sqrt p_2})}Δx=p​2​∗p​1​L1∗(p​2​−p​1​)​∗(1−2∗p​1​−fee∗p​2​fee∗p​1​​)

=> Δx=L1∗(p2−p1)∗(2∗p1−fee∗p2−fee∗p1)p2∗p1∗(2∗p1−fee∗p2)\Delta x = {\Large \frac{L1 * (\sqrt p_2 - \sqrt p_1) * (2 * \sqrt p_1 - fee * \sqrt p_2 - fee * \sqrt p_1)}{\sqrt p_2 * \sqrt p_1 * (2 * \sqrt p_1 - fee * \sqrt p_2)}}Δx=p​2​∗p​1​∗(2∗p​1​−fee∗p​2​)L1∗(p​2​−p​1​)∗(2∗p​1​−fee∗p​2​−fee∗p​1​)​

  • Given L1, p1 and Δx\Delta xΔx, calculate ΔL\Delta LΔL

(L1+ΔL)2=(x1−Δx)(y1+Δy)(L1 + \Delta L)^2 = (x1 - \Delta x)(y1 + \Delta y)(L1+ΔL)2=(x1−Δx)(y1+Δy)

=> (L1+ΔL)2=L12−Δx∗L1∗p1+Δy∗(L1/p1−Δx)(L1 + \Delta L)^2 = L1 ^ 2 - \Delta x * L1 * \sqrt p_1 + \Delta y * (L1 / \sqrt p_1 - \Delta x)(L1+ΔL)2=L12−Δx∗L1∗p​1​+Δy∗(L1/p​1​−Δx)

=> (L1+ΔL)2=L12−Δx∗L1∗p1+ΔL∗2∗p1/fee∗(L1/p1−Δx)(L1 + \Delta L)^2 = L1 ^ 2 - \Delta x * L1 * \sqrt p_1 + \Delta L * 2 * \sqrt p_1 /fee * (L1 / \sqrt p_1 - \Delta x)(L1+ΔL)2=L12−Δx∗L1∗p​1​+ΔL∗2∗p​1​/fee∗(L1/p​1​−Δx)

=> fee∗ΔL2−2∗(L1∗(1−fee)−Δx∗p1)∗ΔL+Δx∗L1∗p1∗fee=0fee * \Delta L^2 - 2 * (L1 * (1 - fee) - \Delta x * \sqrt p_1) * \Delta L + \Delta x * L1 * \sqrt p_1 * fee=0fee∗ΔL2−2∗(L1∗(1−fee)−Δx∗p​1​)∗ΔL+Δx∗L1∗p​1​∗fee=0

Overview

Implementation details

computeSwapStep() Flow

Inputs

Outputs

Swapping formula

Swap exact input from token0 -> token1

Swap exact input from token1 -> token0

Swap exact output from token0 -> token1 (isExactInput = false, isToken0 = false)

Swap exact output token1 -> token0 (isExactInput = false, isToken0 = true)

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
this section