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
  • Introduction
  • Motivation​
  • Mechanism​
  • Struct: Data​
  • Adding liquidity​
  • Removing liquidity​
  • Whitelisting PositionManager​
  • Example​
  • Swapping exact input of Token0 (amount NOT enough to cross tick)​
  • Swap exact output of Token1 (amount enough to cross tick)​
  • Add liquidity​
  • Remove liquidity​

Was this helpful?

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

Anti-Sniping Mechanism

Protecting Against Front-Runners

PreviousPool Process FlowsNextTick-Based Farming

Last updated 1 year ago

Was this helpful?

Introduction

As more value started to accrue towards DeFi, a new opportunity for value extraction arose based on how orders were prioritized on a public blockchain. As it takes time for a transaction to be finalized (i.e. added to a block), front runners could capitalize on the pending transaction whose information was publicly available. This practice came to be known as Maximal Extractable Value (MEV) and more details can be found .

Specific to AMMs, sniping is a specific form of MEV whereby an attacker jumps in front of normal liquidity providers by adding and removing liquidity just before and right after a huge swap. To protect our LPs, KyberSwap Elastic comes with an anti-sniping feature to natively protect them from any potential front-runners.

Motivation

New AMM, which compounds different positions such as Uniswap v3, provides tools for liquidity providers to add and remove liquidity easily in specific ranges. The feature leads to a novel attack, called sniping, where the attacker tries to jump in front of normal liquidity providers by adding and removing liquidity just before and right after a huge swap.

We have collected some to show the impact of the attack.

The sandwich attack can be effectively restrained on the taker's side thanks to parameters limiting how much slippage can be tolerated. However, there is no similar anti-sniping attack mechanism for liquidity providers. Hence, the protocol should introduce a feature that protects liquidity providers from this type of attack.

KyberSwap Elastic's Anti-Sniping Feature is introduced as a lock of reward, which is vested based on the duration of liquidity contribution. The principal difference between attacks and normal activities of liquidity providers is their contribution duration. When liquidity providers supply their funds to the protocol, they take the risk of impermanent loss. However, in the case of an attacker who withdraws their fund immediately, the impermanent loss can be pre-calculated so that their profit is guaranteed.

Mechanism

Struct: Data

Field
Type
Explanation

lastActionTime

uint32

timestamp of last action performed

lockTime

uint32

average start time of lock schedule

unlockTime

uint32

average unlock time of locked fees

feesLocked

uint32

locked rToken qty since last update

Claimable_fees = claimable_amount_of_collected_fees + claimable_amount_of_locked_fees

After calculating the claimable amount of fees, the burnt fees is calculated based on the amount of liquidity that user is withdrawing.

Burnt_fees = Claimable_fees * liquidity_delta / current_liquidity.
Claimable_fees = Claimable_fees - Burnt_fees

As we implement the Anti-Sniping Attack mechanism in the PositionMananger contract, we need to prevent users/contracts from interacting directly with Pool contracts. To do so, we allow only whitelisted PositionManager contracts to call the mint function.

We don't have the whitelisted check in the burn function because:

  • Only the PositionManager holds positions in the Pool contracts, thus, users must interact with PositionManager to burn their positions.

  • In case we upgrade to a new PositionManager contract, all previous PositionManager contracts should still be able to remove liquidity.

The Factory contract stores all whitelisted PositionManager contracts, and have a function called isWhitelistedNFTManager(address) for Pool contracts to check if an address is whitelisted. To make it flexible, the Factory can disable the whitelisting feature, i.e: the isWhitelistedNFTManager function will always return true.

Let's take an example where we have a pool of Token0/Token1 with 3 positions and 5 ticks and the current price (Token0/Token1) is 1. The relationship between price and tick is:

p(i)=1.0001ip(i)=1.0001^ip(i)=1.0001i
Δx=0.0001\Delta_x=0.0001Δx​=0.0001

The next tick is 1 (t_tmp(1)=-1). Calculate square root of price to cross the next tick. We will divide into two functions next if the price moves rightward else back if it moves leftward.

pnext_step(1)=1.0001−1/2=0.99995000375\sqrt{p_{next\_step(1)}} = 1.0001^{-1/2}= 0.99995000375pnext_step(1)​​=1.0001−1/2=0.99995000375

Calculate delta_x_tmp that we need to cross the next tick

deltaxtmp=2(lp+lf)(p−pnext_step(1))2∗pnext_step(1)−fee∗p=2∗(16+3)(1−0.99995000375)1∗(2∗0.99995000375−0.003∗1)=0.00095140342delta_{x_{tmp}} = \frac{2(l_p+l_f)(\sqrt{p}-\sqrt{p_{next\_step(1)}})}{2*\sqrt{p_{next\_step(1)}}-fee*\sqrt{p}} \\=\frac{2*(16+3)(1-0.99995000375)}{1*(2* 0.99995000375-0.003*1)} \\= 0.00095140342deltaxtmp​​=2∗pnext_step(1)​​−fee∗p​2(lp​+lf​)(p​−pnext_step(1)​​)​=1∗(2∗0.99995000375−0.003∗1)2∗(16+3)(1−0.99995000375)​=0.00095140342

We see that delta_x_tmp > delta_x so we do not cross any tick. Now we calculate the collected liquidity l_c:

Lc=fee∗deltax∗p/2=0.003∗0.0001∗1/2=1.5e−7L_c=fee*delta_x*\sqrt{p}/2 = 0.003*0.0001*1/2 = 1.5e-7Lc​=fee∗deltax​∗p​/2=0.003∗0.0001∗1/2=1.5e−7

And calculate the new sqrtPrice:

ptmp=(lp+lf+lc)/(Δx+(lp+lf)/p)=(16+3+1.5e−7)/(0.0001+(16+3)/1)=0.99999474476\sqrt{p_{tmp}}=(l_p+l_f+l_c)/(\Delta_x+(l_p+l_f)/\sqrt{p}) \\=(16+3+1.5e-7)/(0.0001+(16+3)/1) \\= 0.99999474476ptmp​​=(lp​+lf​+lc​)/(Δx​+(lp​+lf​)/p​)=(16+3+1.5e−7)/(0.0001+(16+3)/1)=0.99999474476

Then we calculate delta_y which is the amount of output in token1.

Δy=(lp+lf+lc)∗ptmp−(lp+lf)∗p=(16+3+1.5e−7)∗0.99999474476−(16+3)∗1=−0.00009969956\Delta_y=(l_p+l_f+l_c)*\sqrt{p_{tmp}}-(l_p+l_f)*\sqrt{p} \\=(16+3+1.5e-7)* 0.99999474476-(16+3)*1 \\=-0.00009969956Δy​=(lp​+lf​+lc​)∗ptmp​​−(lp​+lf​)∗p​=(16+3+1.5e−7)∗0.99999474476−(16+3)∗1=−0.00009969956

The delta_y is negative because this is the amount of token1 that taker will take out of the liquidity pool. Now we can update the current price of liquidity pool equal to the new sqrtPrice.

p=ptmp\sqrt{p}=\sqrt{p_{tmp}}p​=ptmp​​

And the collected liquidity is added to the reinvestment liquidity:

lf=lf+lc=3+1.5e−7l_f=l_f+l_c=3+1.5e-7lf​=lf​+lc​=3+1.5e−7
Δy=0.001\Delta_y=0.001Δy​=0.001

The next tick is 1 (t_tmp(1)=-1). Calculate square root of price to cross the next tick. We will divide into two functions next if the price moves rightward else back if it moves leftward.

pnext_step(1)=1.0001−1/2=0.99995000375\sqrt{p_{next\_step(1)}} = 1.0001^{-1/2}= 0.99995000375pnext_step(1)​​=1.0001−1/2=0.99995000375

Calculate delta_y_tmp that we need to cross the next tick

Δytmp=−(lp+lf)(p−pnext_step)(2pnext_step−fee(p+pnext_step))2pnext_step−feep=−(16+3)∗(1−0.99995000375)(2∗0.99995000375−0.003∗(0.99995000375+1))/(2∗0.99995000375−0.003∗1)=−0.00094850171\Delta_{y_{tmp}} = \frac{-(l_p+l_f)(\sqrt{p}-\sqrt{p_{next\_step}})(2\sqrt{p_{next\_step}}-fee(\sqrt{p}+\sqrt{p_{next\_step}}))}{2\sqrt{p_{next\_step}}-fee\sqrt{p}} \\=-(16+3)*(1-0.99995000375)(2* 0.99995000375-0.003*(0.99995000375+1))/(2* 0.99995000375-0.003*1) \\=-0.00094850171Δytmp​​=2pnext_step​​−feep​−(lp​+lf​)(p​−pnext_step​​)(2pnext_step​​−fee(p​+pnext_step​​))​=−(16+3)∗(1−0.99995000375)(2∗0.99995000375−0.003∗(0.99995000375+1))/(2∗0.99995000375−0.003∗1)=−0.00094850171

We see that -delta_y_tmp < delta_y so we cross the next tick. Now we calculate the collected liquidity l_c:

Lc=(Δytmp+p(lp+lf))pricenext_step−(lp+lf)=(−0.00094850171+1∗(16+3))/(0.99995000375)−(16+3)=0.00000142711L_c=\frac{(\Delta_{y_{tmp}}+\sqrt{p}(l_p+l_f))}{\sqrt{price_{next\_step}}}-(l_p+l_f) \\=(-0.00094850171+1*(16+3))/(0.99995000375)-(16+3) \\= 0.00000142711Lc​=pricenext_step​​(Δytmp​​+p​(lp​+lf​))​−(lp​+lf​)=(−0.00094850171+1∗(16+3))/(0.99995000375)−(16+3)=0.00000142711

Then we can update the delta_x:

Δx=(lp+lf+lc)/pnext_step−(lp+lf)/p=(16+3+0.00000142711)/0.99995000375−(16+3)/1=0.00095140342\Delta_x=(l_{p}+l_f+l_c)/\sqrt{p_{next\_step}}-(l_{p}+l_f)/\sqrt{p} \\=(16+3+ 0.00000142711)/0.99995000375 - (16+3)/1 \\= 0.00095140342Δx​=(lp​+lf​+lc​)/pnext_step​​−(lp​+lf​)/p​=(16+3+0.00000142711)/0.99995000375−(16+3)/1=0.00095140342

Now we calculate the rest amount of \Delta_y need to be swapped:

Δyr=Δy+Δytmp=0.001−0.00094850171=0.00005149829\Delta_{y_{r}}=\Delta_y+\Delta_{y_{tmp}} \\=0.001-0.00094850171 \\= 0.00005149829Δyr​​=Δy​+Δytmp​​=0.001−0.00094850171=0.00005149829

Now we calculate the additional pool tokens will be minted:

smint=lp∗lc/(Lflast(lp+lf))∗s=(16∗0.00000142711/(3∗(16+3.00000142711)))∗3=0.00000120177s_{mint}=l_p*l_c/(L_{f_{last}}(l_p+l_f))*s =(16* 0.00000142711/(3*(16+ 3.00000142711)))*3 \\= 0.00000120177smint​=lp​∗lc​/(Lflast​​(lp​+lf​))∗s=(16∗0.00000142711/(3∗(16+3.00000142711)))∗3=0.00000120177

So we will update the total supply of the reinvestment tokens:

s=s+smint=3+0.00000120177=3.00000120177s=s+s_{mint}=3+ 0.00000120177 = 3.00000120177s=s+smint​=3+0.00000120177=3.00000120177

Now we calculate the sqrt price of the next step:

pnext_step(2)=1.0001−2/2=0.99990000999\sqrt{p_{next\_step(2)}} = 1.0001^{-2/2}= 0.99990000999pnext_step(2)​​=1.0001−2/2=0.99990000999

When we cross to tick -2 we must also update liquidity of the pool - l_p_tmp. It will subtract the liquidity net of the tick. In this simple example, so l_p_tmp=l_p=16, meanwhile the temporary liquidity of the reinvestment curve l_f_tmp=l_f+l_c=3.00000142711 Calculate delta_y_tmp that we need to cross the next tick

Δytmp=−(lptmp+lftmp)(pnext_step(1)−pnext_step(2))(2pnext_step(2)−fee(pnext_step(1)+pnext_step(2)))2pnext_step(2)−feepnext_step(1)=−(16+3.00000142711)(0.99995000375−0.99990000999)(20.99990000999−0.003∗(0.99990000999+0.99995000375))/(2∗0.99990000999−0.003∗0.99995000375)=−0.00094845454\Delta_{y_{tmp}} = -\frac{(l_{p_{tmp}}+l_{f_{tmp}})(\sqrt{p_{next\_step(1)}}-\sqrt{p_{next\_step(2)}})(2\sqrt{p_{next\_step(2)}}-fee(\sqrt{p_{next\_step(1)}}+\sqrt{p_{next\_step(2)}}))}{2\sqrt{p_{next\_step(2)}}-fee\sqrt{p_{next\_step(1)}}} \\=-(16+3.00000142711)(0.99995000375-0.99990000999)(2 0.99990000999-0.003*(0.99990000999 + 0.99995000375))/(2* 0.99990000999-0.003* 0.99995000375) \\=-0.00094845454Δytmp​​=−2pnext_step(2)​​−feepnext_step(1)​​(lptmp​​+lftmp​​)(pnext_step(1)​​−pnext_step(2)​​)(2pnext_step(2)​​−fee(pnext_step(1)​​+pnext_step(2)​​))​=−(16+3.00000142711)(0.99995000375−0.99990000999)(20.99990000999−0.003∗(0.99990000999+0.99995000375))/(2∗0.99990000999−0.003∗0.99995000375)=−0.00094845454

So -delta_y_tmp>delta_y_r, we do not cross one more tick. Then we move to next step to calculate the new amount of collected fee.

Lc2∗pnext_step(1)∗fee+2((lptmp+lftmp)∗fee∗pnext_step(1)−(lptmp+lftmp)∗pnext_step(1)−Δy)lc+(lptmp+lftmp)∗fee∗Δy=00.003∗0.99995000375∗lc2+2∗((16+3.00000142711)∗0.003∗0.99995000375−(16+3.00000142711)∗0.99995000375−0.001)lc+(16+3.00000142711)∗0.003∗0.001=00.00299985001∗lc2−37.8861086961∗lc+0.000057=0lc=0.0000015045085390746784L_c^2*\sqrt{p_{next\_step(1)}}*fee+ 2((l_{p_{tmp}}+l_{f_{tmp}})*fee *\sqrt{p_{next\_step(1)}} - (l_{p_{tmp}}+l_{f_{tmp}})*\sqrt{p_{next\_step(1)}} - \Delta_y)l_c+(l_{p_{tmp}}+l_{f_{tmp}})*fee*\Delta_y=0 \\ 0.003* 0.99995000375*l_c^2+2*((16+ 3.00000142711)*0.003* 0.99995000375-(16+ 3.00000142711)* 0.99995000375-0.001)l_c+(16+ 3.00000142711)*0.003*0.001=0 \\ 0.00299985001*l_c^2 -37.8861086961*l_c+ 0.000057 =0 \\l_c=0.0000015045085390746784Lc2​∗pnext_step(1)​​∗fee+2((lptmp​​+lftmp​​)∗fee∗pnext_step(1)​​−(lptmp​​+lftmp​​)∗pnext_step(1)​​−Δy​)lc​+(lptmp​​+lftmp​​)∗fee∗Δy​=00.003∗0.99995000375∗lc2​+2∗((16+3.00000142711)∗0.003∗0.99995000375−(16+3.00000142711)∗0.99995000375−0.001)lc​+(16+3.00000142711)∗0.003∗0.001=00.00299985001∗lc2​−37.8861086961∗lc​+0.000057=0lc​=0.0000015045085390746784

And calculate the new sqrtPrice:

ptmp=(−Δyr+(lptmp+lftmp)/pnext_step(1))/(lptmp+lftmp+lc)=(−0.00005149829+(16+3.00000142711)∗0.99995000375)/(16+3.00000142711+0.0000015045085390746784)=0.99994721413\sqrt{p_{tmp}}=(-\Delta_{y_{r}}+(l_{p_{tmp}}+l_{f_{tmp}})/\sqrt{p_{next\_step(1)}})/(l_{p_{tmp}}+l_{f_{tmp}}+l_c) \\=(-0.00005149829 +(16+3.00000142711)* 0.99995000375)/(16+ 3.00000142711 + 0.0000015045085390746784) \\=0.99994721413ptmp​​=(−Δyr​​+(lptmp​​+lftmp​​)/pnext_step(1)​​)/(lptmp​​+lftmp​​+lc​)=(−0.00005149829+(16+3.00000142711)∗0.99995000375)/(16+3.00000142711+0.0000015045085390746784)=0.99994721413

Then we calculate delta_x which is the amount of input in token0.

Δx=Δx+(lptmp+lftmp+lc)/ptmp−(lptmp+lftmp)/pnext_step(1)=0.00095140342+(16+3.00000142711+0.0000015045085390746784)/0.99994721413−(16+3.00000142711)/0.99995000375=0.00100591624\Delta_x =\Delta_x + (l_{p_{tmp}}+l_{f_{tmp}}+l_c)/\sqrt{p_{tmp}}-(l_{p_{tmp}}+l_{f_{tmp}})/\sqrt{p_{next\_step(1)}} \\= 0.00095140342+(16+ 3.00000142711 + 0.0000015045085390746784)/ 0.99994721413-(16+ 3.00000142711)/0.99995000375 \\=0.00100591624Δx​=Δx​+(lptmp​​+lftmp​​+lc​)/ptmp​​−(lptmp​​+lftmp​​)/pnext_step(1)​​=0.00095140342+(16+3.00000142711+0.0000015045085390746784)/0.99994721413−(16+3.00000142711)/0.99995000375=0.00100591624

Now we calculate the additional pool tokens will be minted:

smint=lptmp∗lc/(Lftmp(lp+lftmp+lc))∗s=(16∗0.0000015045085390746784/(3.00000142711∗(16+3.00000142711+0.0000015045085390746784)))∗3=0.00000126695s_{mint}=l_{p_{tmp}}*l_c/(L_{f_{tmp}}(l_p+l_{f_{tmp}}+l_c))*s \\=(16* 0.0000015045085390746784/(3.00000142711*(16+ 3.00000142711+ 0.0000015045085390746784)))*3 \\= 0.00000126695smint​=lptmp​​∗lc​/(Lftmp​​(lp​+lftmp​​+lc​))∗s=(16∗0.0000015045085390746784/(3.00000142711∗(16+3.00000142711+0.0000015045085390746784)))∗3=0.00000126695

So we will update the total supply of the reinvestment tokens:

s=s+smint=3.00000120177+0.00000126695=3.00000246872s=s+s_{mint}= 3.00000120177+ 0.00000126695=3.00000246872s=s+smint​=3.00000120177+0.00000126695=3.00000246872

Now we can update the current price of the liquidity pool equal to the new sqrtPrice.

p=ptmp\sqrt{p}=\sqrt{p_{tmp}}p​=ptmp​​

And the collected liquidity is added to the reinvestment liquidity:

lf=lftmp+lc=3.00000142711+0.0000015045085390746784=3.00000293162l_f=l_{f_{tmp}}+l_c= 3.00000142711 + 0.0000015045085390746784\\= 3.00000293162lf​=lftmp​​+lc​=3.00000142711+0.0000015045085390746784=3.00000293162

Liquidity provider add liquidity to the pool to price range from 0.99995000375 to 1.00004999875 (tick -1 to tick 1), which means the current price is in the price range of the the position, the amount of liquidity to be added:

ΔL=1\Delta_L=1ΔL​=1

Now we need to calculate delta_x, delta_y taken from user:

Δx=Δlp−Δlptickupper=1/1−1/1.00004999875=0.00004999625Δy=Δl(p−pticklower)=1−0.99995000375=0.00004999625\Delta_x=\frac{\Delta_l}{\sqrt{p}}-\frac{\Delta_l}{\sqrt{p_{tick_{upper}}}}=1/1-1/1.00004999875= 0.00004999625 \\\Delta_y=\Delta_l(\sqrt{p}-\sqrt{p_{tick_{lower}}})=1-0.99995000375= 0.00004999625Δx​=p​Δl​​−ptickupper​​​Δl​​=1/1−1/1.00004999875=0.00004999625Δy​=Δl​(p​−pticklower​​​)=1−0.99995000375=0.00004999625

When adding liquidity to a position, it updates data values for that position and calculates the amount of claimable reinvestment tokens to be sent to the user. In this case, we consider that there is a different between the last time balances of reinvestment curve has been updated. The new reinvestment liquidity l_f 3.1 meanwhile the last time we updated the balances, the reinvestment liquidity l_f_last is 3. Now we calculate the additional pool tokens will be minted:

smint=lp(lf−lflast)/(Lflast(lp+lf))∗s=(16∗(3.1−3)/(3∗(16+3.1)))∗3=0.0837696335s_{mint}=l_p(l_{f}-l_{f_{last}})/(L_{f_{last}}(l_p+l_f))*s =(16*(3.1-3)/(3*(16+3.1)))*3= 0.0837696335smint​=lp​(lf​−lflast​​)/(Lflast​​(lp​+lf​))∗s=(16∗(3.1−3)/(3∗(16+3.1)))∗3=0.0837696335

So we will update the total supply of the reinvestment tokens:

s=s+smint=3+0.0837696335=3.0837696335s=s+s_{mint}=3+ 0.0837696335 = 3.0837696335s=s+smint​=3+0.0837696335=3.0837696335

We also need to update the balances of every liquidity providers and the "last" reinvestment liquidity (l_f_last). Then we transfer the collected pool tokens from addressPool to the user if the amount of reinvestment tokens collected of the user is greater than 0.

Similar to add liquidity when removing liquidity from a position, it updates data values for that position and calculates the amount of claimable reinvestment tokens, as well as the amount of reinvestment tokens to be burnt. After calculating the claimable amount of fees, the burnt fees is calculated based on the amount of liquidity that user is withdrawing.

Adding liquidity

When adding liquidity to a position, it updates values for that position and calculates the amount of claimable reinvestment tokens to be sent to the user.

The values are calculates based on the unlockTime, lockedTime, lastActionTime, currentTime, feesLocked and feeSinceLastAction, the formula can be found .

Removing liquidity

When removing liquidity from a position, it updates values for that position and calculates the amount of claimable reinvestment tokens, as well as the amount of reinvestment tokens to be burnt.

Whitelisting PositionManager

Example

Swapping exact input of Token0 (amount NOT enough to cross tick)

Swap exact output of Token1 (amount enough to cross tick)

Add liquidity

Remove liquidity

here
​
data
​
​
​
​
​
​
​
​
​
​
Data
Data
here