# OVERVIEW

All-in-one DeFi platform on Flow

{% embed url="<https://app.increment.fi>" %}

{% hint style="info" %}
[Increment Finance](https://app.increment.fi) is a leading DeFi (Decentralized Finance) platform built on Flow, allowing users to trade / swap, lend / borrow tokens, join in liquid staking, and customize more liquidity & yield strategies all in one place.&#x20;
{% endhint %}


# Background

\*This was an ecosystem overview given on 2022. We've launched the mentioned protocols by 2024, and now planning new products further strengthening the DeFi ecosystem on Flow.

Increment Labs is building several DeFi protocols on Flow blockchain, with the vision to become the liquidity & yield engine for the Flow ecosystem.

[Flow blockchain](https://www.onflow.org/) has been well-known for NFTs and the team behind it, i.e. Dapper Labs, creator of CryptoKitties and ERC721 standard, with a bunch of successful projects like [NBA TopShot](https://nbatopshot.com/), [Rarible](https://rarible.com/), [ChainMonsters](https://chainmonsters.com/), [Blocto](https://blocto.portto.io/en/), [Flovatar](https://flovatar.com/), etc. launched on mainnet in 2022.

Beyond digital assets and NFTs, as Flow being a generalized public blockchain, we do see the demand for decentralized financial products is growing but still the infrastructure is missing.

## Problems

* With more assets and fungible tokens launching on Flow (like My, USDC), a permissionless decentralized exchange is a must-have to bootstrap liquidity pools, trading volumes and on-chain economy. Moreover, DEX will serve as one of the instant-exit strategies for stFlow.&#x20;
* Currently, there’s no way for flow holders to lend out their leisure flow tokens for some yields, or to borrow stablecoin assets while still maintaining their fungible token position.
* Although staking flow tokens help secure the network and generate staking rewards, the staked tokens will be illiquid for at least two epochs (\~14 days) before being transferrable again.&#x20;

## Solutions

Increment Labs is building 3 major DeFi protocols on Flow to solve the above-mentioned problems and missing infrastructures.&#x20;

### Permisionless DEX (AMM Swap)

Blocto has built an DEX on Flow (i.e. BloctoSwap), however, it has certain restrictions on tokens, users, projects and devs:

1. **Limited tokenlist:** Users cannot search or import any arbitrary fungible token on Flow.
2. **Centralized pool management**: Trading pairs can only be created by Blocto team, and the pair must be paired with tUSDT (which USDT bridged from ETH to Flow, still centralized and fully-custodied by Blocto), so it's not optimal for Market Makers as liquidity is pivoted around tUSDT.
3. **Rudimentary routing algo**: Swap output is not the optimal to users &#x20;
4. **Missing on-chain price oracle**

We anticipate more fungible tokens and projects will be launched on Flow, as well as assets bridged from other chains such as ceWBTC by Celer. So a purely permissionless DEX will be beneficial to all users, community, projects and Flow's onchain economy as a whole.

Last but not least, AMM will also serve as an **instant-exit strategy** for stFlow (see below) holders.

### Decentralized Money Market

Lending is the cornerstone of any financial system, which has also been proven as one of the catalysts of the DeFi boomer. The potential and total addressable market size of lending is large enough: according to [defillama’s data](https://defillama.com/protocols/lending), total value locked (TVL) in the decentralized lending platforms is almost 50 billion USD by December 2021.

Lending generates yield for leisure capital, powers the on-chain economy with more leverage and assets. Lending platforms itself also capture a significant portion of [value](https://www.tokenterminal.com/terminal/markets/lending) in terms of protocol revenue and P/S ratio.

So the first product we’ve been developing and will launch soon is a decentralized money market for fungible tokens on Flow.&#x20;

* First batch of supported markets include: Flow, FUSD, USDC
* Second batch of markets to support soon: BloctoToken, Teleported-USDT, stFlow
* Explore DAO-based governance to list new FungibleToken assets as well as adjust per-market risk parameters like collateralization ratio, market borrow cap, interest rate model, etc.&#x20;

### Non-Custodial Liquid Staking

It’s nice to enjoy a [8.3% staking APR](https://www.stakingrewards.com/earn/flow/), however, it comes at the cost of locking flow tokens for 2 epochs. Essentially every Proof-of-Stake blockchain faces the same problem, Ethereum 2.0, Terra, and Solana, etc. are solving it by introducing non-custodial liquid staking service like [Lido](<https://lido.fi/ >), a.k.a. staking derivative.

We tackle the problem in a similar approach: A staking contract accepts user deposit of flow tokens, mint and return stFlow (staked flow) tokens back to users at the rate of 1:1, the staking contract then stakes the deposited funds to DAO-selected node operators.

stFlow token holds the following rights:&#x20;

* To redeem the underlying staked flow along with earned staking rewards.
* stFlow can be used as collaterals in Increment.Fi decentralized money market.
* stFlow holders looking for instant redemption can exit through flow <=> stFlow liquidity pool through DEX.

## Summary

These products work independently and each of them tackles one problem to try to solve it well. Unified together, we’re expecting <mark style="color:blue;">Increment.Fi</mark> to become an interest earning and capital efficient DeFi liquidity engine for the benefit of all Flow users and ecosystem as a whole.


# Decentralized Exchange

{% hint style="info" %}
**Increment Swap** is a *dual-mode* decentralized exchange (DEX) on Flow blockchain supporting both **volatile pairs** (adopting Uniswap-V2 CPAMM curve, suitable for uncorrelated assets like `Flow/USDC`) and **pegged pairs** (adopting Solidly-Stableswap curve, suitable for correlated assets like `USDC/FUSD`, `Flow/stFlow`, et al.).

It allows users to create arbitrary trading pairs between fungible tokens in a permissionless way, including basic functionalities like `CreatePair`, `AddLiquidity`, `RemoveLiquidity`, `Swap`, `TWAP-Oracle`, `Flashloan`, etc.

* It adopts the factory pattern that each unique trading pair is deployed using the `SwapPair` template file, with a factory contract storing all deployed pairs.
* On-chain time-weighted average price oracle of each of the trading pair is supported by snapshoting cumulative data on the first call of any block. Developers can choose different window size to support different TWAP data.
* The trading fee is set to `0.3%` for volatile pairs and `0.04%` for pegged pairs by default. All of the trading fees goes to liquidity providers (LP) initially. However, there's a switch that factory admin can opt to turn on to earn `1/6` of the trading fees.&#x20;
* There're several fee parameters configurable by the factory admin:
  * Trading fee of volatile pairs (default to 0.3%)
  * Trading fee of pegged pairs (default to 0.04%)
  * Rate of flashloan repayment (default to 0.05%)
  * feeTo switch (default off, i.e. no protocol cut from the trading fees)
  * protocol fee cut (default to 0% as feeTo is off, once feeTo is on it's default to 1/6)<br>
    {% endhint %}


# CPAMM DEX

<https://app.increment.fi/swap>&#x20;


# User Guidance

## **1. Connect Wallet** <a href="#id-33d9" id="id-33d9"></a>

The first step is to connect the app with a wallet so we can use the decentralized exchange (dex) products. In this case we’ll go ahead with the Blocto wallet. It also supports Lilico wallet - a non-custodial wallet (metamask-like) on Flow.

![](https://miro.medium.com/max/1400/0*HH_OvXGZkuzE1zkW)

At this stage it will require your email for sign in/register, a one time passcode will be sent to your email. If you’re a frequent Blocto user, it might also automatically connect.

![](https://miro.medium.com/max/1400/0*Hh_8h-iAjFZ9p6YC)

## **2. Swap** <a href="#id-5c4f" id="id-5c4f"></a>

Let us take a look at the swap feature. Here the user can choose which tokens she wants to trade. The input token equals the token you currently own and want to trade for another token (output token).

![](https://miro.medium.com/max/1400/0*XvYsXezHIP5UJgq4)

### **2.1** **Multihops/Router**

The increment.fi swap supports multihops/router, which means that the swap will make sure that you end up with the maximum amount possible for your given output token.

![](https://miro.medium.com/max/1400/0*VNMLW5x1uaQ1GOcg)

### **2.2 Support celer bridge token**

We also support Celer bridged tokens (ceTOKEN). The Celer cBridge is a cross-chain token bridge with deep liquidity for users. Currently eight assets are supported which you can see on the screenshot below.

Learn more about Celer & FLOW [here](https://www.onflow.org/post/partner-spotlight-celer-network-to-support-digital-asset-and-nft-bridging-on-flow-across-20-chains).

![](https://miro.medium.com/max/1400/0*xxPnlplBcJE6cLc0)

### **2.3 Search and Import any Token**

What if the token you want to trade cannot be found in the drop-down list? As long as you know the token contract address, just paste it into the search bar and click “Search More”. Clicking the “Import” button to import it into the default token list and everything is set up.

![](https://miro.medium.com/max/1400/0*FfqW4wnzjtrOVBXs)

In most cases clicking the "Import" button would automatically parse the address and import given token into the dropdown menu. In case it fails for whatever reason (e.g. parser failure, non-standard token contract implementation, etc.), it can still be manually imported by clicking "Import Custom Token" menu:

&#x20;    ![](/files/16cCFza9t0vjSS9L1QZt)         =>        ![](/files/nEcVAtb8MxdH0sXCro8J)&#x20;

(\* It's not compulsory, but if you want to get the project token included in the default dropdown menu, please refer to [this](/protocols/decentralized-exchange/token-listing).)

### **2.4 Swap Settings**

The users can also adjust their swap settings, if they think this increases their chances of a successful transaction. This includes the following parameters:

* Slippage limit: you may set a new slippage limit. Please note that increasing your slippage limit may result in an unexpectedly bad exchange rate. Your transaction may be frontruned.
* Transaction deadline: you may extend the transaction beyond the standard 30 minutes. However, please note that this may lead to your trade executing at a subpar exchange rate as the market price may change during that time.
* Enable mulithops: this option is by default turned on. This is for the routing algorithm to calculate and split a trade into multiple paths to achieve the best output.

![](https://miro.medium.com/max/1400/0*4umrxMJY2QrYke_k)

## **3. Liquidity Pools** <a href="#id-60a6" id="id-60a6"></a>

Besides the swap, the user can decide to become a liquidity provider. This means that the user will add two different tokens into a liquidity pool and form a pair or add to an existing pair.

The liquidity providers will receive a part of the transaction fees as a reward but take note that being a liquidity provider comes with the **risk of impairment loss.**

### **3.1 Create a New Pair**

As mentioned before, any user can create new trading pairs that are not existed yet, for example:

![](https://miro.medium.com/max/1400/0*dJrCFizVG_7e5klu)

For liquidity pairs that already exist, the page will show that the **pair already exists.**

![](https://miro.medium.com/max/1400/0*NrM5gU75AdejWh0d)

### 3.2 Add Liquidity

Once the pair is created, any user can add liquidity into the pool. The first liquidity provider is the one who sets the initial price of the pool. They are incentivized to deposit **an equal value of both tokens** into the pool.

<figure><img src="/files/xMTWvfvVhMFoUybpyvUO" alt=""><figcaption></figcaption></figure>

### 3.2.1 ⚡️ Zap: Add liquidity with a single asset

You can also add liquidity to any trading pair using a single asset: some of the given asset\_A will be automatically swapped to asset\_B and then adding liquidity for the pair `asset_A <> asset_B`, just in 1 click.

<figure><img src="/files/DmsVz0K67ppTCDzz7woU" alt=""><figcaption></figcaption></figure>

`Zap` could be very convenient as you don't need to calculate and balance double-sided assets before adding liquidity. But since `Zap` adds liquidity by means of `Swap` (trading) first, if your size is big (for example: `Price Impact` > 3%, ymmv), you'd better still add liquidity in the normal way (clicking the `All assets` tab).

## 4. Tutorial by Flowverse

<https://twitter.com/flowverse_/status/1533696877983846400>


# AMM 101

### 1. Identify FT on Flow

Unlike on EVM, simply using a contract address is **not** enough to identify FTs on FVM. The unique identifier for FT is composed of: `A.16-byte`-`address.name`.&#x20;

For example:

* `A.b19436aae4d94622.FiatToken` is USDC's **unique identifier** on mainnet.&#x20;
* Also `ceWETH` and `ceWBTC` (Celer-Bridged wETH & wBTC from ETH) are deployed under the same address but with different identifiers:  `A.231cc0dbbcffc4b7.ceWETH`, and `A.231cc0dbbcffc4b7.ceWBTC`.

### 2. Interact with FT on Flow

#### Paths

FT on FVM conforms to the `FungibleToken` [interface](https://flow-view-source.com/mainnet/account/0xf233dcee88fe0abe/contract/FungibleToken). One specific FT is represented as a Vault resource and stored directly under the holder' account storage area.

So each FT is also associated with several [paths](https://docs.onflow.org/cadence/language/accounts/#paths) used to interact with it. Check the `tokenlist` file [here](https://github.com/IncrementFi/token-list/blob/main/tokenlist.mainnet.json) for FT details on mainnet.&#x20;

#### FT Resource Initialization

Unlike FT on EVM, one cannot 'airdrop' FT to arbitrary address without the receiver account first initializing the FT resource once (using `FT.createEmptyVault()` method).&#x20;

* Example transaction: `init_usdc_vault.cdc`

```
import FungibleToken from 0xf233dcee88fe0abe  // mainnet
import FiatToken from 0xb19436aae4d94622      // mainnet

transaction() {
    prepare(signer: AuthAccount) {
        let vaultPath = /storage/USDCVault
        let receiverPath = /public/USDCVaultReceiver
        let balancePath = /public/USDCVaultBalance

        if signer.borrow<&FungibleToken.Vault>(from: vaultPath) == nil {
            signer.save(<- FiatToken.createEmptyVault(), to: vaultPath)
            signer.link<&FiatToken.Vault{FungibleToken.Receiver}>(receiverPath, target: vaultPath)
            signer.link<&FiatToken.Vault{FungibleToken.Balance}>(balancePath, target: vaultPath)
        }
    }
}
```

The initialization only needs to be done once per holder account for one specific FT. After that any further action like: deposit / withdraw / etc. can be performed flawlessly.

**\***&#x4E;ote: `FlowToken` is also FT but it's the only exception that it doesn't need initialization - as the init step has been performed when the account is created.

### 3. CPAMM Principles

Check Uniswap-V2 whitepaper here: <https://uniswap.org/whitepaper.pdf>

### 4. Understanding Impermanent loss (IL)

![Source: https://docs.uniswap.org/protocol/V2/concepts/advanced-topics/understanding-returns](/files/DaTEZcx4quq7bCvIDj5b)


# Deployment Addresses

### Mainnet

<table><thead><tr><th>Contract</th><th>Address</th><th>Comment</th><th data-hidden></th></tr></thead><tbody><tr><td>SwapFactory</td><td><a href="https://www.flowdiver.io/account/0xb063c16cac85dbd1">0xb063c16cac85dbd1</a></td><td>Pair creation and data container of all uni-v2 style (volatile) swap pair addresses</td><td></td></tr><tr><td>SwapPair (Template contract)</td><td><a href="https://www.flowdiver.io/account/0xecbda466e7f191c7">0xecbda466e7f191c7</a></td><td>A dual-mode swap pair contract template for deploying both volatile and stable pairs. (Pure code, no state) </td><td></td></tr><tr><td>SwapError</td><td><a href="https://www.flowdiver.io/account/0xb78ef7afa52ff906">0xb78ef7afa52ff906</a></td><td>Common error codes</td><td></td></tr><tr><td>SwapInterfaces</td><td><a href="https://www.flowdiver.io/account/0xb78ef7afa52ff906">0xb78ef7afa52ff906</a></td><td>Swap related interface definitions all-in-one</td><td></td></tr><tr><td>SwapConfig</td><td><a href="https://www.flowdiver.io/account/0xb78ef7afa52ff906">0xb78ef7afa52ff906</a></td><td>Common configs &#x26; helpful swap library functions</td><td></td></tr><tr><td>SwapRouter</td><td><a href="https://www.flowdiver.io/account/0xa6850776a94e6551">0xa6850776a94e6551</a></td><td>Router &#x26; apis support a chained swap trade among uni-v2 style volatile pairs</td><td></td></tr></tbody></table>

### Testnet

<table><thead><tr><th>Contract</th><th>Address</th><th data-hidden></th></tr></thead><tbody><tr><td>SwapFactory</td><td><a href="https://testnet.flowdiver.io/account/0x6ca93d49c45a249f">0x6ca93d49c45a249f</a></td><td></td></tr><tr><td>SwapRouter</td><td><a href="https://testnet.flowdiver.io/account/0x2f8af5ed05bbde0d">0x2f8af5ed05bbde0d</a></td><td></td></tr><tr><td>SwapPair (Template contract)</td><td><a href="https://testnet.flowdiver.io/account/0x7afd587a5d5e2efe">0x7afd587a5d5e2efe</a></td><td></td></tr><tr><td>SwapInterfaces, SwapConfig, SwapError</td><td><a href="https://testnet.flowdiver.io/account/0x8d5b9dd833e176da">0x8d5b9dd833e176da</a></td><td></td></tr></tbody></table>


# Stableswap DEX

<https://app.increment.fi/swap>&#x20;


# Introduction

Stableswap is a type of amm algorithm that offers low slippage trading for two assets that are **highly correlated** in nature. For exmaple, it is very suitable for pairs like `USDC<>FUSD` and `stFlow<>Flow`.&#x20;

The algorithm we're using is solidly stableswap algorithm, a CFMM with the invariant:

$$
x^3 y + x y^3 >= K
$$

It's simple and elegant, doesn't consume a lot of onchain computation units comparing with other complex stableswap algorithms, yet it provides a much smaller slippage than the cpamm dex, and  enables more capital efficiency with the same amount of liquidity.&#x20;

<figure><img src="/files/XgQdJb9Or0fedWme4kw4" alt=""><figcaption></figcaption></figure>

The original solidly stableswap curve works well for "hard" pegged assets, for example, stablecoins USDC/USDT/FUSD, or different version of bridged BTC like ceWBTC/whWBTC et al., but it's still subject to arbitrages for liquid staking assets (`stFlow`) - as stFlow's value (against flow) increases over time due to the auto-compounding of staking rewards.&#x20;

To make it more suitable for liquid staking pairs, we've extended the original solidly stableswap algorithm further, which we call it "weighted-solidly-stableswap-curve", i.e.:.

$$
(px)^3y +(px)y^3 >= K; s.t.: p = stFlow/Flow
$$

Where `p` is the weight and taken from Liquid Staking smart contracts directly. After each epoch advancement, it'll increase value and then the bonding curve will be adjusted a little bit automatically.

<figure><img src="/files/81CDRq3ZaKsH5Xs1cMaH" alt=""><figcaption></figcaption></figure>


# User Guidance

### 1. Swap

The stableswap is by default enabled in liquidity sources, and you can choose to turn it on/off in the settings panel and apply the change.

It is straightforward and similar to using the existing Swap product: just choose the tokens you'd like to swap and the routing algorithm automatically splits the trade across multiple swap pairs to give the best result:&#x20;

<figure><img src="/files/up34GPwgr4xoEveiwsaK" alt=""><figcaption></figcaption></figure>

### 2. Stableswap pair-creation

Now you have to choose whether to create a stableswap pair or a normal swap pair (i.e. “volatile” pair).&#x20;

Noting that stableswap pair is only designed for assets that are highly correlated, for example: stablecoin assets or liquid staking assets. ***If you’re not sure about this, you should just create volatile pairs most of the time.***&#x20;

*(**⚠️ Causion**: Creating stableswap pairs for uncorrelated assets may cause you to lose money - you've been warned on this!)*

&#x20;                                                ![](https://lh3.googleusercontent.com/GrXODGpFa1tFAlAlX3YOo0u_bFQ28BrRwEyZQSs7K4d4X0YBotsa-Ku0GJiweY-raDqj6ubR74r_Of0ToTb7_odfNRCsYnI4--fWeuby7fTxWI9BslI25WF4ajDosdivCSIjhFKJigDaZn5XscEMs3E)

### 3. Liquidity management

Liquidity provision is similar as before , the only difference is that there’s a “1≈1” symbol to differentiate stable pairs from normal swap pairs:

&#x20;                                                ![](https://lh5.googleusercontent.com/xj1YP_Sn74M_kw584ZruTHZSTzWT1BBz9zhtk9roi1shdxSsjVtWhX5tya1GZR1lrqux0P0MgtSWQdf2jftU8EiYP1uyXm_5O9z_v5HkQeSZ8flaHj02S_GvZcYwjihhvixtd6TeGd_nhOuBgVkONHk)


# Deployment Addresses

### Mainnet

<table><thead><tr><th width="273.3333333333333">Contract</th><th>Address</th><th>Comment</th></tr></thead><tbody><tr><td>StableSwapFactory</td><td><a href="https://www.flowdiver.io/account/0xb063c16cac85dbd1">0xb063c16cac85dbd1</a></td><td>Data container of stableswap pair addresses</td></tr><tr><td>SwapPair (Template contract)</td><td><a href="https://www.flowdiver.io/account/0xecbda466e7f191c7">0xecbda466e7f191c7</a></td><td>A dual-mode swap pair contract template for deploying both volatile and stable pairs. (Pure code, no state)</td></tr><tr><td>SwapConfig</td><td><a href="https://www.flowdiver.io/account/0xb78ef7afa52ff906">0xb78ef7afa52ff906</a></td><td>Common configs &#x26; helpful swap library functions </td></tr></tbody></table>

### Testnet

|                              |                                                                               |
| ---------------------------- | ----------------------------------------------------------------------------- |
| StableSwapFactory            | [0x6ca93d49c45a249f](https://testnet.flowdiver.io/account/0x6ca93d49c45a249f) |
| SwapPair (Template contract) | [0x7afd587a5d5e2efe](https://testnet.flowdiver.io/account/0x7afd587a5d5e2efe) |
| SwapConfig                   | [0x8d5b9dd833e176da](https://testnet.flowdiver.io/account/0x8d5b9dd833e176da) |


# DEX Aggregator

{% hint style="info" %}
Increment is now supporting **DEX Aggregation** and **Smart Order Routing** on Flow. From now on, users have a unified access to multiple DEX platforms on Flow, and enjoy the best swap rates in one-click trading.
{% endhint %}

#### Aggregated liquidity sources

* Increment-V1
* Increment-Stableswap
* Bloctoswap
* Metapier

#### Read [more](https://medium.com/coinmonks/introducing-the-dex-aggregation-and-smart-order-routing-9c467e4c3673) here.&#x20;


# Smart Contract API

## Create a Pair

### createPair

```javascript
/// SwapFactory.cdc

pub fun createPair(
    token0Vault: @FungibleToken.Vault,
    token1Vault: @FungibleToken.Vault,
    accountCreationFee: @FungibleToken.Vault,
    stableMode: Bool
): Address
```

* Example transaction `create_pair_usdc_fusd.cdc`

```javascript
import FlowToken from 0x1654653399040a61
import FungibleToken from 0xf233dcee88fe0abe
import SwapFactory from 0xb063c16cac85dbd1

// Deploy a SwapPair given token{0|1}'s TokenName and contract address.
//`stableMode` specifies whether the pair uses Uniswap-V2 algorithm (stableMode:false) or Solidly-Stableswap algorithm (stableMode:true).
transaction(Token0Name: String, Token0Addr: Address, Token1Name: String, Token1Addr: Address, stableMode: Bool) {
    prepare(userAccount: AuthAccount) {
        let flowVaultRef = userAccount.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)!
        assert(flowVaultRef.balance >= 0.002, message: "Insufficient balance to create pair, minimum balance requirement: 0.002 flow")
        let accountCreationFeeVault <- flowVaultRef.withdraw(amount: 0.001)
        
        let token0Vault <- getAccount(Token0Addr).contracts.borrow<&FungibleToken>(name: Token0Name)!.createEmptyVault()
        let token1Vault <- getAccount(Token1Addr).contracts.borrow<&FungibleToken>(name: Token1Name)!.createEmptyVault()
        SwapFactory.createPair(token0Vault: <-token0Vault, token1Vault: <-token1Vault, accountCreationFee: <-accountCreationFeeVault, stableMode: stableMode)
    }
}
```

## Get Pair & LpToken Info

### Get Pairs' Addresses

```javascript
/// SwapFactory.cdc && StableSwapFactory.cdc

pub fun getPairAddress(token0Key: String, token1Key: String): Address?
pub fun getAllPairsLength(): Int
pub fun getAllStableSwapPairsLength(): Int
pub fun getSlicedPairs(from: UInt64, to: UInt64): [Address]
```

| Param        | Type        | Comments                                    |
| ------------ | ----------- | ------------------------------------------- |
| `from`       | `UInt64`    | Start Index                                 |
| `to`         | `UInt64`    | End Index                                   |
| Return Value | `[Address]` | An array of deployed trading pair addresses |

* Get number of all deployed trading pairs and an array of deployed trading pair addresses.
* Example script `get_all_pair_addresses.cdc`:

```javascript
import SwapFactory from 0xb063c16cac85dbd1

pub fun main(): [Address] {
  let len = SwapFactory.getAllPairsLength()
  if (len == 0) {
    return []
  } else {
    return SwapFactory.getSlicedPairs(from: 0, to: UInt64.max)
  }
}
```

### getPairInfo

```javascript
/// SwapFactory.cdc && StableSwapFactory.cdc

pub fun getPairInfo(token0Key: String, token1Key: String): AnyStruct?
pub fun getSlicedPairInfos(from: UInt64, to: UInt64): [AnyStruct]
```

<table><thead><tr><th>Param</th><th>Type</th><th>Comments</th></tr></thead><tbody><tr><td><code>token0Key</code></td><td><code>String</code></td><td>token0's unique identifier, e.g.:  <code>A.3c5959b568896393.FUSD</code></td></tr><tr><td><code>token1Key</code></td><td><code>String</code></td><td>token1's unique identifier, e.g.: <code>A.b19436aae4d94622.FiatToken</code></td></tr><tr><td>Return Value</td><td><code>AnyStruct?</code></td><td><p><code>nil</code> if the pair doesn't exist, otherwise returns detailed pair info, e.g.: </p><pre><code>[
    token0Key,
    token1Key,
    token0Balance,
    token1Balance,
    pairAddress,
    lpTokenBalance,
    swapFeeBps,
    isStableswap,
    stableCurveP
]
</code></pre></td></tr></tbody></table>

```javascript
/// SwapPair.cdc

pub resource PairPublic: SwapInterfaces.PairPublic {
    pub fun getPairInfo(): [AnyStruct] {}
}
```

* Example script to get `PairInfo` given the pair address:

```javascript
import SwapInterfaces from 0xb78ef7afa52ff906                                      
import SwapConfig from 0xb78ef7afa52ff906                                          
                                                                                   
pub fun main(pairAddr: Address): [AnyStruct] {                                                                                                                                                            
  let pairPublicRef = getAccount(pairAddr)                                         
    .getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath)        
    .borrow()                                                                      
    ?? panic("cannot borrow reference to PairPublic resource")                     
                                                                                   
  return pairPublicRef.getPairInfo()                                               
}
```

* Example script \```get_all_pair_infos.cdc`:``

```javascript
import SwapFactory from 0xb063c16cac85dbd1

pub fun main(): [AnyStruct] {
  let len = SwapFactory.getAllPairsLength()
  if (len == 0) {
    return []
  } else {
    return SwapFactory.getSlicedPairInfos(from: 0, to: UInt64.max)
  }
}
```

### LpTokenCollection

Liquidity Provider (LP) of a trading pair will receive corresponding FT (i.e. LpToken) representing LP's pro rata share of that pair. LP may provide liquidity to different trading pairs and receive multiple different LpTokens. All these LpTokens are grouped within the `LpTokenCollection` resource, with methods exposing LpToken details:

```javascript
/// SwapFactory.cdc

pub resource LpTokenCollection: SwapInterfaces.LpTokenCollectionPublic {

    pub fun getAllLPTokens(): [Address] {}
    
    pub fun getLpTokenBalance(pairAddr: Address): UFix64 {}
    
    pub fun deposit(pairAddr: Address, lpTokenVault: @FungibleToken.Vault) {}
    
    pub fun withdraw(pairAddr: Address, amount: UFix64): @FungibleToken.Vault {}
    
}
```

* Example script to check all the LPed pairs and liquidity shares of a given account:

```javascript
/// lpinfo.cdc

import SwapConfig from 0xb78ef7afa52ff906
import SwapInterfaces from 0xb78ef7afa52ff906
import SwapFactory from 0xb063c16cac85dbd1

pub fun main(userAddr: Address): {Address: AnyStruct} {
    var lpTokenCollectionPublicPath = SwapConfig.LpTokenCollectionPublicPath
    let lpTokenCollectionCap = getAccount(userAddr).getCapability<&{SwapInterfaces.LpTokenCollectionPublic}>(lpTokenCollectionPublicPath)
    if lpTokenCollectionCap.check() == false {
        return {}
    }
    let lpTokenCollectionRef = lpTokenCollectionCap.borrow()!
    let liquidityPairAddrs = lpTokenCollectionRef.getAllLPTokens()
    var res: {Address: AnyStruct} = {}
    for pairAddr in liquidityPairAddrs {
        let pairRef = getAccount(pairAddr).getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath).borrow()
            ?? panic("cannot borrow reference to PairPublic")
        let pairInfo = pairRef.getPairInfo()
        let token0Key = pairInfo[0] as! String
        let token1Key = pairInfo[1] as! String
        let token0Balance = pairInfo[2] as! UFix64
        let token1Balance = pairInfo[3] as! UFix64
        let totalLp = pairInfo[5] as! UFix64
        let lpTokenAmount = lpTokenCollectionRef.getLpTokenBalance(pairAddr: pairAddr)
        res[pairAddr] = {
            "token0": token0Key,
            "token1": token1Key,
            "token0Amount": lpTokenAmount / totalLp * token0Balance,
            "token1Amount": lpTokenAmount / totalLp * token1Balance,
            "shareOfPool": lpTokenAmount / totalLp * 100.0
        }
    }
    return res
}

/// $ flow scripts execute lpinfo.cdc <0xUserAccount> --network mainnet
```

## Swap

A straightforward way to contruct a `Swap` transaction is to use the [`SwapRouter`](https://flow-view-source.com/mainnet/account/0xa6850776a94e6551/contract/SwapRouter), which provides a set of useful methods below.&#x20;

### Calculate output / input amount

#### getAmountsOut

```javascript
/// SwapRouter.cdc

pub fun getAmountsOut(
    amountIn: UFix64,
    tokenKeyPath: [String]
): [UFix64]
```

<table><thead><tr><th width="201.71055618615216">Param</th><th width="166.8860655827209">Type</th><th>Comments</th></tr></thead><tbody><tr><td><code>amountIn</code></td><td><code>UFix64</code></td><td>Input token amount for the FT <code>tokenKeyPath[0]</code>, e.g. <code>50.0</code></td></tr><tr><td><code>tokenKeyPath</code></td><td><code>[String]</code></td><td><p>An array of FT identifiers denoting the chained-swap path, e.g.: <code>[A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken]</code> => denoting the swap path of  <code>[FUSD -> Flow -> USDC]</code>.</p><p></p><p><code>tokenKeyPath.length</code> must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.</p></td></tr><tr><td>Return Vaule</td><td><code>[UFix64]</code></td><td>Calculated maximum output FT amounts following the given swap path, e.g. <code>[50.0, 10.0, 48.0]</code></td></tr></tbody></table>

* Given the input amount of a FT, with an array of FT identifiers denoting the chained-swap path, calculates all subsequent maximum output token amounts.&#x20;
* Useful for calculating output token amounts before calling [#perform-chained-swap](#perform-chained-swap "mention")

#### getAmountsIn

```javascript
/// SwapRouter.cdc

pub fun getAmountsIn(
    amountOut: UFix64,
    tokenKeyPath: [String]
): [UFix64] 
```

| Param          | Type       | Comments                                                                                                                                                                                                                                                                                                                                                                          |
| -------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `amountOut`    | `UFix64`   | Expected output amount of the FT to receive, e.g. `48.0`                                                                                                                                                                                                                                                                                                                          |
| `tokenKeyPath` | `[String]` | <p>An array of FT identifiers denoting the chained-swap path, e.g.: <code>\[A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken]</code> => denoting the swap path of  <code>\[FUSD -> Flow -> USDC]</code>.</p><p></p><p><code>tokenKeyPath.length</code> must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.</p> |
| Return Value   | `[UFix64]` | Calculated minimum input FT amounts following the given swap path, e.g. `[50.0, 10.0, 48.0]`                                                                                                                                                                                                                                                                                      |

* Given the expected output amount of a FT, with an array of FT identifiers denoting the chained-swap path, calculates the minimum input FT amounts required to buy the given `amountOut`.
* Useful for calculating input token amounts before calling [#perform-chained-swap](#perform-chained-swap "mention")

### Perform chained-swap

#### swapExactTokensForTokens

```javascript
/// SwapRouter.cdc

pub fun swapExactTokensForTokens(
    exactVaultIn: @FungibleToken.Vault,
    amountOutMin: UFix64,
    tokenKeyPath: [String],
    deadline: UFix64
): @FungibleToken.Vault
```

<table><thead><tr><th width="196.40132860173145">Param</th><th width="150">Type</th><th>Comments</th></tr></thead><tbody><tr><td><code>exactVaultIn</code></td><td><code>@FT.Vault</code></td><td>Input FT to sell, its full balance will be used.</td></tr><tr><td><code>amountOutMin</code></td><td><code>UFix64</code></td><td>The minimum amount of output token that must be received, otherwise the tx will revert.</td></tr><tr><td><code>tokenKeyPath</code></td><td><code>[String]</code></td><td><p>An array of FT identifiers denoting the chained-swap path, e.g.: <code>[A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken]</code> => denoting the swap path of  <code>[FUSD -> Flow -> USDC]</code>.</p><p></p><p><code>tokenKeyPath.length</code> must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.</p></td></tr><tr><td><code>deadline</code></td><td><code>UFix64</code></td><td>Unix timestamp after which the tx will revert.</td></tr><tr><td>Return Value</td><td><code>@FT.Vault</code></td><td>Output FT resource</td></tr></tbody></table>

* To receive *as many output FT as* possible for swapping the exact amount of input FT, by following the given swap path.
* Example transaction `swap_exact_flow_to_usdc.cdc`:

```javascript
import FungibleToken from 0xf233dcee88fe0abe
import SwapRouter from 0xa6850776a94e6551

transaction(
    exactAmountIn: UFix64,
    amountOutMin: UFix64,
    path: [String],
    to: Address,
    deadline: UFix64
) {
    prepare(userAccount: AuthAccount) {
        let tokenInVaultPath = /storage/flowTokenVault
        let tokenOutReceiverPath = /public/USDCVaultReceiver

        let inVaultRef = userAccount.borrow<&FungibleToken.Vault>(from: tokenInVaultPath)
            ?? panic("Could not borrow reference to the owner's in FT.Vault")
        /// Note: Receiver (to) should already have out FT.Vault initialized, otherwise tx reverts.
        let outReceiverRef = getAccount(to).getCapability(tokenOutReceiverPath)
            .borrow<&{FungibleToken.Receiver}>()
            ?? panic("Could not borrow receiver reference to the recipient's out FT.Vault")

        let exactVaultIn <- inVaultRef.withdraw(amount: exactAmountIn)
        let vaultOut <- SwapRouter.swapExactTokensForTokens(
            exactVaultIn: <-exactVaultIn,
            amountOutMin: amountOutMin,
            tokenKeyPath: path,
            deadline: deadline
        )
        outReceiverRef.deposit(from: <-vaultOut)
    }
}
```

#### swapTokensForExactTokens

```javascript
/// SwapRouter.cdc

pub fun swapTokensForExactTokens(
    vaultInMax: @FungibleToken.Vault,
    exactAmountOut: UFix64,
    tokenKeyPath: [String],
    deadline: UFix64
): @[FungibleToken.Vault] {
```

| Param            | Type          | Comments                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vaultInMax`     | `@FT.Vault`   | Input FT to sell, whose balance is the maximum amount can be used before the tx reverts. Any remaining input token will be put in `returnValue[1]`.                                                                                                                                                                                                                               |
| `exactAmountOut` | `UFix64`      | The exact amount of output FT expected to receive.                                                                                                                                                                                                                                                                                                                                |
| `tokenKeyPath`   | `[String]`    | <p>An array of FT identifiers denoting the chained-swap path, e.g.: <code>\[A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken]</code> => denoting the swap path of  <code>\[FUSD -> Flow -> USDC]</code>.</p><p></p><p><code>tokenKeyPath.length</code> must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.</p> |
| `deadline`       | `UFix64`      | Unix timestamp after which the tx will revert.                                                                                                                                                                                                                                                                                                                                    |
| Return Value     | `@[FT.Vault]` | <p>2-element array of FT resources.<br>\* <code>returnValue\[0]</code>: output token resource, whose balance will be <code>exactAmountOut</code>.<br>\* <code>returnValue\[1]</code>: Any remaining input token resource.</p>                                                                                                                                                     |

* To receive the exact amount of output FT for swapping *as few input FT as* possible, by following the given swap path.
* Example transaction `swap_flow_to_exact_usdc.cdc`:

```javascript
import FungibleToken from 0xf233dcee88fe0abe
import SwapRouter from 0xa6850776a94e6551

transaction(
    amountInMax: UFix64,
    exactAmountOut: UFix64,
    path: [String],
    to: Address,
    deadline: UFix64
) {
    prepare(userAccount: AuthAccount) {
        let tokenInVaultPath = /storage/flowTokenVault
        let tokenOutReceiverPath = /public/USDCVaultReceiver
        
        let inVaultRef = userAccount.borrow<&FungibleToken.Vault>(from: tokenInVaultPath)
            ?? panic("Could not borrow reference to the owner's in FT.Vault")
        /// Note: Receiver (to) should already have out FT.Vault initialized, otherwise tx reverts.
        let outReceiverRef = getAccount(to).getCapability(tokenOutReceiverPath)
            .borrow<&{FungibleToken.Receiver}>()
            ?? panic("Could not borrow receiver reference to the recipient's out FT.Vault")
            
        let vaultInMax <- inVaultRef.withdraw(amount: amountInMax)
        let swapResVault <- SwapRouter.swapTokensForExactTokens(
            vaultInMax: <-vaultInMax,
            exactAmountOut: exactAmountOut,
            tokenKeyPath: path,
            deadline: deadline
        )
        let vaultOut <- swapResVault.removeFirst()
        let vaultInLeft <- swapResVault.removeLast()
        destroy swapResVault
        
        outReceiverRef.deposit(from: <-vaultOut)
        /// Deposit any remaining input FT back
        inVaultRef.deposit(from: <-vaultInLeft)
    }
}
```

* Note: Using `flow-cli` [tool](https://docs.onflow.org/flow-cli/) in the commandline environment, or `fcl-js` [library](https://docs.onflow.org/fcl/) as long with  tx.cdc / script.cdc to interact with smart contracts directly.
* \*`SwapRouter` provides an easy way to perform chained swaps among non-stableswap pairs, but it won't work acrossing stableswap pairs: as for any two given tokens, there could be two SwapPair for them, the existing `SwapRouter` interfaces cannot easily support it. To perform chained swap among non-stableswap pairs and stableswap pairs, one needs to take an address array of pairs and understand SwapPair's raw apis (read below).

### Helper functions and Raw apis

#### Helper functions in SwapConfig

```javascript
/// SwapConfig.cdc

// For a non-stableswap pair (under the standard constant product formula x * y = k)
// Given pair reserves, swapFeeRateBps(0 ~ 10000), and the exact input amount of an asset, returns the maximum output amount of the other asset.
pub fun getAmountOutVolatile(amountIn: UFix64, reserveIn: UFix64, reserveOut: UFix64, swapFeeRateBps: UInt64): UFix64

// For a non-stableswap pair, given pair reserves, swapFeeRateBps, and the exact output amount of an asset wanted, returns the required (minimum) input amount of the other asset
pub fun getAmountInVolatile(amountOut: UFix64, reserveIn: UFix64, reserveOut: UFix64, swapFeeRateBps: UInt64): UFix64

// For a stableswap pair (under the solidly-stableswap formula: x^3 * y + x * y^3 = k)
// Given pair reserves, swapFeeRateBps, stableswap p-value(usually 1.0), and the exact input amount of an asset, returns the maximum output amount of the other asset
pub fun getAmountOutStable(amountIn: UFix64, reserveIn: UFix64, reserveOut: UFix64, p: UFix64, swapFeeRateBps: UInt64): UFix64

// For a stableswap pair, given pair reserves, swapFeeRateBps, stableswap p-value, and the exact input amount of an asset, returns the required (minimum) input amount of the other asset
pub fun getAmountInStable(amountOut: UFix64, reserveIn: UFix64, reserveOut: UFix64, p: UFix64, swapFeeRateBps: UInt64): UFix64

// Can be used to compute the spot price of a non-stableswap pair.
pub fun quote(amountA: UFix64, reserveA: UFix64, reserveB: UFix64): UFix64

// Can be used to compute the spot price of a stableswap pair.
pub fun quoteStable(amountA: UFix64, reserveA: UFix64, reserveB: UFix64, p: UFix64): UFix64

// Calculates the latest cumulative price of the given SwapPair, using the last cumulative record and current spot price.
// Usually a helper function in building dex-based TWAP oracle.
pub fun getCurrentCumulativePrices(pairAddr: Address): [UInt256; 3]
```

#### Raw apis in SwapPair

```javascript
/// Each SwapPair.cdc

// The default rate is: 30 bps (0.3%) for non-stableswap pairs, and 4 bps (0.04%) for stableswap pairs.
pub fun getSwapFeeBps(): UInt64
pub fun isStableSwap(): Bool
// 1.0 for all non-stableswap pairs and most stableswap pairs. For now the only stableswap pair with a non-1.0 p-value is the `stFlow<>Flow` pair.
pub fun getStableCurveP(): UFix64

pub fun getAmountIn(amountOut: UFix64, tokenOutKey: String): UFix64
pub fun getAmountOut(amountIn: UFix64, tokenInKey: String): UFix64

// DEX-based TWAP oracle related helpful data, see twap oracle related section below for more examples.
pub fun getPrice0CumulativeLastScaled(): UInt256
pub fun getPrice1CumulativeLastScaled(): UInt256
pub fun getBlockTimestampLast(): UFix64

// Raw swap function, one can swap with pair contract directly and build any of the chained routes.
// If `exactAmountOut` is not-nil then a safety check ensures swapped output will not be smaller than the given value.
pub fun swap(vaultIn: @FungibleToken.Vault, exactAmountOut: UFix64?): @FungibleToken.Vault

// Request a flashloan from the current SwapPair, the default interest rate is 5 bps (0.05%). 
// See flashloan related section below for explanations and examples.
pub fun flashloan(executorCap: Capability<&{SwapInterfaces.FlashLoanExecutor}>, requestedTokenVaultType: Type, requestedAmount: UFix64, params: {String: AnyStruct}) 
```

## Add & Remove Liquidity

### AddLiquidity

```javascript
/// SwapPair.cdc

pub fun addLiquidity(
    tokenAVault: @FungibleToken.Vault,
    tokenBVault: @FungibleToken.Vault
): @FungibleToken.Vault 
```

* It's *not* recommended to use the low-level `addLiquidity` method directly, unless you're the 1st LP to set the initial price.  &#x20;
* Use below example transaction to do slippage check and add liquidity at the ideal ratio:&#x20;

```javascript
import FungibleToken from 0xFungibleToken
import SwapFactory from 0xSwapFactory
import StableSwapFactory from 0xStableSwapFactory
import SwapInterfaces from 0xSwapInterfaces
import SwapConfig from 0xSwapConfig
import SwapError from 0xSwapError

transaction(
    token0Key: String,
    token1Key: String,
    token0InDesired: UFix64,
    token1InDesired: UFix64,
    token0InMin: UFix64,
    token1InMin: UFix64,
    deadline: UFix64,
    token0VaultPath: StoragePath,
    token1VaultPath: StoragePath,
    stableMode: Bool
) {
    prepare(userAccount: AuthAccount) {
        assert(deadline >= getCurrentBlock().timestamp, message:
            SwapError.ErrorEncode(
                msg: "AddLiquidity: expired ".concat(deadline.toString()).concat(" < ").concat(getCurrentBlock().timestamp.toString()),
                err: SwapError.ErrorCode.EXPIRED
            )
        )
        let pairAddr = (stableMode)? 
            StableSwapFactory.getPairAddress(token0Key: token0Key, token1Key: token1Key) ?? panic("AddLiquidity: nonexistent stable pair ".concat(token0Key).concat(" <-> ").concat(token1Key).concat(", create stable pair first"))
            :
            SwapFactory.getPairAddress(token0Key: token0Key, token1Key: token1Key) ?? panic("AddLiquidity: nonexistent pair ".concat(token0Key).concat(" <-> ").concat(token1Key).concat(", create pair first"))
        let pairPublicRef = getAccount(pairAddr).getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath).borrow()!
        /*
            pairInfo = [
                SwapPair.token0Key,
                SwapPair.token1Key,
                SwapPair.token0Vault.balance,
                SwapPair.token1Vault.balance,
                SwapPair.account.address,
                SwapPair.totalSupply
                ...
            ]
        */
        let pairInfo = pairPublicRef.getPairInfo()
        var token0In = 0.0
        var token1In = 0.0
        var token0Reserve = 0.0
        var token1Reserve = 0.0
        if token0Key == (pairInfo[0] as! String) {
            token0Reserve = (pairInfo[2] as! UFix64)
            token1Reserve = (pairInfo[3] as! UFix64)
        } else {
            token0Reserve = (pairInfo[3] as! UFix64)
            token1Reserve = (pairInfo[2] as! UFix64)
        }
        if token0Reserve == 0.0 && token1Reserve == 0.0 {
            token0In = token0InDesired
            token1In = token1InDesired
        } else {
            var amount1Optimal = SwapConfig.quote(amountA: token0InDesired, reserveA: token0Reserve, reserveB: token1Reserve)
            if (amount1Optimal <= token1InDesired) {
                assert(amount1Optimal >= token1InMin, message:
                    SwapError.ErrorEncode(
                        msg: "SLIPPAGE_OFFSET_TOO_LARGE expect min".concat(token1InMin.toString()).concat(" got ").concat(amount1Optimal.toString()),
                        err: SwapError.ErrorCode.SLIPPAGE_OFFSET_TOO_LARGE
                    )
                )
                token0In = token0InDesired
                token1In = amount1Optimal
            } else {
                var amount0Optimal = SwapConfig.quote(amountA: token1InDesired, reserveA: token1Reserve, reserveB: token0Reserve)
                assert(amount0Optimal <= token0InDesired)
                assert(amount0Optimal >= token0InMin, message:
                    SwapError.ErrorEncode(
                        msg: "SLIPPAGE_OFFSET_TOO_LARGE expect min".concat(token0InMin.toString()).concat(" got ").concat(amount0Optimal.toString()),
                        err: SwapError.ErrorCode.SLIPPAGE_OFFSET_TOO_LARGE
                    )
                )
                token0In = amount0Optimal
                token1In = token1InDesired
            }
        }
        
        let token0Vault <- userAccount.borrow<&FungibleToken.Vault>(from: token0VaultPath)!.withdraw(amount: token0In)
        let token1Vault <- userAccount.borrow<&FungibleToken.Vault>(from: token1VaultPath)!.withdraw(amount: token1In)
        let lpTokenVault <- pairPublicRef.addLiquidity(
            tokenAVault: <- token0Vault,
            tokenBVault: <- token1Vault
        )
        
        let lpTokenCollectionStoragePath = SwapConfig.LpTokenCollectionStoragePath
        let lpTokenCollectionPublicPath = SwapConfig.LpTokenCollectionPublicPath
        var lpTokenCollectionRef = userAccount.borrow<&SwapFactory.LpTokenCollection>(from: lpTokenCollectionStoragePath)
        if lpTokenCollectionRef == nil {
            destroy <- userAccount.load<@AnyResource>(from: lpTokenCollectionStoragePath)
            userAccount.save(<-SwapFactory.createEmptyLpTokenCollection(), to: lpTokenCollectionStoragePath)
            userAccount.link<&{SwapInterfaces.LpTokenCollectionPublic}>(lpTokenCollectionPublicPath, target: lpTokenCollectionStoragePath)
            lpTokenCollectionRef = userAccount.borrow<&SwapFactory.LpTokenCollection>(from: lpTokenCollectionStoragePath)
        }
        lpTokenCollectionRef!.deposit(pairAddr: pairAddr, lpTokenVault: <- lpTokenVault)
    }
}
```

### RemoveLiquidity

```javascript
/// SwapPair.cdc

pub fun removeLiquidity(
    lpTokenVault: @FungibleToken.Vault
) : @[FungibleToken.Vault] {
```

* Example transaction below to burn lpToken and deposit back removed two-sided liquidities:

```javascript
import FungibleToken from 0xFungibleToken
import SwapFactory from 0xSwapFactory
import StableSwapFactory from 0xStableSwapFactory
import SwapInterfaces from 0xSwapInterfaces
import SwapConfig from 0xSwapConfig
import SwapError from 0xSwapError

transaction(
    token0Key: String,
    token1Key: String,
    lpTokenAmount: UFix64,
    token0OutMin: UFix64,
    token1OutMin: UFix64,
    deadline: UFix64,
    token0VaultPath: StoragePath,
    token1VaultPath: StoragePath,
    stableMode: Bool
) {
    prepare(userAccount: AuthAccount) {
        assert(deadline >= getCurrentBlock().timestamp, message:
            SwapError.ErrorEncode(
                msg: "RemoveLiquidity: expired ".concat(deadline.toString()).concat(" < ").concat(getCurrentBlock().timestamp.toString()),
                err: SwapError.ErrorCode.EXPIRED
            )
        )
        let pairAddr = (stableMode)? 
            StableSwapFactory.getPairAddress(token0Key: token0Key, token1Key: token1Key) ?? panic("AddLiquidity: nonexistent stable pair ".concat(token0Key).concat(" <-> ").concat(token1Key).concat(", create stable pair first"))
            :
            SwapFactory.getPairAddress(token0Key: token0Key, token1Key: token1Key) ?? panic("AddLiquidity: nonexistent pair ".concat(token0Key).concat(" <-> ").concat(token1Key).concat(", create pair first"))
        
        let lpTokenCollectionRef = userAccount.borrow<&SwapFactory.LpTokenCollection>(from: SwapConfig.LpTokenCollectionStoragePath)
            ?? panic("RemoveLiquidity: cannot borrow reference to LpTokenCollection")

        let lpTokenRemove <- lpTokenCollectionRef.withdraw(pairAddr: pairAddr, amount: lpTokenAmount)
        let tokens <- getAccount(pairAddr).getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath).borrow()!.removeLiquidity(lpTokenVault: <-lpTokenRemove)
        let token0Vault <- tokens[0].withdraw(amount: tokens[0].balance)
        let token1Vault <- tokens[1].withdraw(amount: tokens[1].balance)
        destroy tokens

        assert(token0Vault.balance >= token0OutMin && token1Vault.balance >= token1OutMin, message:
            SwapError.ErrorEncode(
                msg: "RemoveLiquidity: INSUFFICIENT_REMOVE_LIQUIDITY_OUT_AMOUNT",
                err: SwapError.ErrorCode.SLIPPAGE_OFFSET_TOO_LARGE
            )
        )

        /// Here does not detect whether the local receiver vault exsit.
        let localVault0Ref = userAccount.borrow<&FungibleToken.Vault>(from: token0VaultPath)!
        let localVault1Ref = userAccount.borrow<&FungibleToken.Vault>(from: token1VaultPath)!
        if token0Vault.isInstance(localVault0Ref.getType()) {
            localVault0Ref.deposit(from: <-token0Vault)
            localVault1Ref.deposit(from: <-token1Vault)
        } else {
            localVault0Ref.deposit(from: <-token1Vault)
            localVault1Ref.deposit(from: <-token0Vault)
        
        }
    }
}
```

## Build a TWAP Oracle

* DEX-based TWAP (time-weighted-average-price) oracles can be built using the last cumulative prices recorded in each SwapPair.&#x20;
* However, to correctly use & integrate the twap-oracle into your projects, you must ensure the sampling of the cumulative price data are kept up to date. As long as your oracle is up to date, you can depend on it to produce average prices.&#x20;

Check below 2 examples for the sampling (`update()`) and twap-data consuming (`twap()`).

### Fixed-window TWAP oracle example:

```javascript
import StableSwapFactory from 0xStableSwapFactoryAddr
import SwapFactory from 0xSwapFactoryAddr
import SwapInterfaces from 0xSwapInterfacesAddr
import SwapConfig from 0xSwapConfigAddr

/// Fixed window oracle
///
/// Calculate the average price for the entire period based on the on-chain dex swap pair.
/// note that the price average is only guaranteed to be over at least 1 period, but may be over a longer period
///
pub contract FixedWindowOracleExample {
    /// Window period of the average in seconds
    pub let PERIOD: UInt64
    /// A.contractAddr.contractName: A.11111111.FlowToken, A.2222222.FUSD
    pub let token0Key: String
    pub let token1Key: String
    pub let isStableswap: Bool
    /// pair address in dex
    pub let pairAddr: Address

    /// Average price for each PERIOD, updated once per PERIOD (updating interval could be longer than 1 PERIOD)
    pub var price0Average: UFix64
    pub var price1Average: UFix64

    /// Cumulative price/timestamp for the last update
    pub var price0CumulativeLastScaled: UInt256
    pub var price1CumulativeLastScaled: UInt256
    pub var blockTimestampLast: UFix64


    /// Sampling: update the accumulated price if it exceeds the period.
    pub fun update() {
        let now = getCurrentBlock().timestamp
        let timeElapsed = now - self.blockTimestampLast
        assert(timeElapsed >= UFix64(self.PERIOD), message: "PERIOD_NOT_ELAPSED ".concat(timeElapsed.toString().concat("s")))

        let res = SwapConfig.getCurrentCumulativePrices(pairAddr: self.pairAddr)
        let currentPrice0CumulativeScaled = res[0]
        let currentPrice1CumulativeScaled = res[1]
        let timeElapsedScaled = SwapConfig.UFix64ToScaledUInt256(timeElapsed)
        let price0AverageScaled = SwapConfig.underflowSubtractUInt256(currentPrice0CumulativeScaled, self.price0CumulativeLastScaled) * SwapConfig.scaleFactor / timeElapsedScaled
        let price1AverageScaled = SwapConfig.underflowSubtractUInt256(currentPrice1CumulativeScaled, self.price1CumulativeLastScaled) * SwapConfig.scaleFactor / timeElapsedScaled

        self.price0Average = SwapConfig.ScaledUInt256ToUFix64(price0AverageScaled)
        self.price1Average = SwapConfig.ScaledUInt256ToUFix64(price1AverageScaled)

        self.price0CumulativeLastScaled = currentPrice0CumulativeScaled
        self.price1CumulativeLastScaled = currentPrice1CumulativeScaled
        self.blockTimestampLast = now
    }

    /// Queries twap price data
    /// Returns 0.0 for data n/a or invalid input token
    pub fun twap(tokenKey: String): UFix64 {
        if (tokenKey == self.token0Key) {
            return self.price0Average
        } else if (tokenKey == self.token1Key) {
            return self.price1Average
        } else {
            return 0.0
        }
    }

    /// @Param - token{A|B}Key: e.g. A.f8d6e0586b0a20c7.FUSD
    /// @Param - isStableswap: whether the twap is for stableswap pair or not
    /// @Param - period: average period (in seconds)
    init(tokenAKey: String, tokenBKey: String, isStableswap: Bool, period: UInt64) {
        self.PERIOD = period
        self.isStableswap = isStableswap
        self.pairAddr = isStableswap ?
            StableSwapFactory.getPairAddress(token0Key: tokenAKey, token1Key: tokenBKey) ?? panic("non-existent stableswap-pair") :
            SwapFactory.getPairAddress(token0Key: tokenAKey, token1Key: tokenBKey) ?? panic("non-existent pair")

        let pairPublicRef = getAccount(self.pairAddr).getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath).borrow()
            ?? panic("cannot borrow reference to PairPublic")
        let pairInfo = pairPublicRef.getPairInfo()
        self.token0Key = pairInfo[0] as! String
        self.token1Key = pairInfo[1] as! String
        let reserve0 = pairInfo[2] as! UFix64
        let reserve1 = pairInfo[3] as! UFix64
        assert(reserve0 * reserve1 != 0.0, message: "There's no liquidity in the pair")

        self.price0CumulativeLastScaled = pairPublicRef.getPrice0CumulativeLastScaled()
        self.price1CumulativeLastScaled = pairPublicRef.getPrice1CumulativeLastScaled()
        self.blockTimestampLast = pairPublicRef.getBlockTimestampLast()
        self.price0Average = 0.0
        self.price1Average = 0.0
    }
}
```

### Sliding-window TWAP oracle example

```javascript
import StableSwapFactory from 0xStableSwapFactoryAddr
import SwapFactory from 0xSwapFactoryAddr
import SwapInterfaces from 0xSwapInterfacesAddr
import SwapConfig from 0xSwapConfigAddr

/// Sliding window oracle
///
pub contract SlidingWindowOracleExample {
    /// The amount of time (in seconds) the moving average should be computed, e.g. 24 hours
    pub let windowSize: UInt64
    /// The number of observation data stored for windowSize.
    /// As granularity increases from 2, more frequent updates are needed, but moving averages become more precise.
    /// twap data is computed over intervals with sizes in the range: [windowSize - (windowSize / granularity) * 2, windowSize]
    pub let granularity: UInt64
    /// The amount of time once an update() is needed, periodSize * granularity == windowSize.
    pub let periodSize: UInt64
    /// A.contractAddr.contractName: A.11111111.FlowToken, A.2222222.FUSD
    pub let token0Key: String
    pub let token1Key: String
    pub let isStableswap: Bool
    /// pair address in dex
    pub let pairAddr: Address
    /// An array of price observation data of the pair
    access(self) let pairObservations: [Observation]

    pub struct Observation {
        pub let timestamp: UFix64
        pub let price0CumulativeScaled: UInt256
        pub let price1CumulativeScaled: UInt256

        init(t: UFix64, p0Scaled: UInt256, p1Scaled: UInt256) {
            self.timestamp = t
            self.price0CumulativeScaled = p0Scaled
            self.price1CumulativeScaled = p1Scaled
        }
    }


    /// Returns the index of the observation corresponding to the given timestamp
    pub fun observationIndexOf(timestamp: UFix64): UInt64 {
        return UInt64(timestamp) / self.periodSize % self.granularity
    }

    /// Returns the index of the earliest observation of a windowSize (relative to the given timestamp)
    pub fun firstObservationIndexInWindow(timestamp: UFix64): UInt64 {
        let idx = self.observationIndexOf(timestamp: timestamp)
        return (idx + 1) % self.granularity
    }

    /// Sampling: update the cumulative price for the observation at the current timestamp.
    /// Each observation is updated at most once per periodSize.
    pub fun update() {
        let now = getCurrentBlock().timestamp
        let idx = self.observationIndexOf(timestamp: now)
        let ob = self.pairObservations[idx]
        let timeElapsed = now - ob.timestamp

        if (timeElapsed > UFix64(self.periodSize)) {
            let timeElapsedScaled = SwapConfig.UFix64ToScaledUInt256(timeElapsed)
            let res = SwapConfig.getCurrentCumulativePrices(pairAddr: self.pairAddr)
            let currentPrice0CumulativeScaled = res[0]
            let currentPrice1CumulativeScaled = res[1]
            self.pairObservations[idx] = Observation(t: now, p0Scaled: currentPrice0CumulativeScaled, p1Scaled: currentPrice1CumulativeScaled)
        }
    }

    /// Queries twap price data of the time range [now - [windowSize, windowSize - 2 * periodSize], now]
    /// Returns 0.0 for data n/a or invalid input token
    pub fun twap(tokenKey: String): UFix64 {
        let now = getCurrentBlock().timestamp
        let first_ob_idx = self.firstObservationIndexInWindow(timestamp: now)
        let first_ob = self.pairObservations[first_ob_idx]
        let timeElapsed = now - first_ob.timestamp

        assert(UInt64(timeElapsed) <= self.windowSize, message: "missing historical observations, more update() needed")
        assert(UInt64(timeElapsed) >= self.windowSize - self.periodSize * 2, message: "should never happen")

        let res = SwapConfig.getCurrentCumulativePrices(pairAddr: self.pairAddr)
        let currentPrice0CumulativeScaled = res[0]
        let currentPrice1CumulativeScaled = res[1]
        let timeElapsedScaled = SwapConfig.UFix64ToScaledUInt256(timeElapsed)

        if (tokenKey == self.token0Key) {
            let price0AverageScaled = SwapConfig.underflowSubtractUInt256(currentPrice0CumulativeScaled, first_ob.price0CumulativeScaled) * SwapConfig.scaleFactor / timeElapsedScaled
            return SwapConfig.ScaledUInt256ToUFix64(price0AverageScaled)
        } else if (tokenKey == self.token1Key) {
            let price1AverageScaled = SwapConfig.underflowSubtractUInt256(currentPrice1CumulativeScaled, first_ob.price1CumulativeScaled) * SwapConfig.scaleFactor / timeElapsedScaled
            return SwapConfig.ScaledUInt256ToUFix64(price1AverageScaled)
        } else {
            return 0.0
        }
    }

    /// @Param - token{A|B}Key: e.g. A.f8d6e0586b0a20c7.FUSD
    /// @Param - isStableswap: whether the twap is for stableswap pair or not
    /// @Param - windowSize: The amount of time (in seconds) the moving average should be computed, e.g.: 24 hours (86400)
    /// @Param - granularity: The number of observation data stored for windowSize, e.g.: 24. The more granularity, the more precise the moving average, but with the cost of more frequent updates are needed.
    init(tokenAKey: String, tokenBKey: String, isStableswap: Bool, windowSize: UInt64, granularity: UInt64) {
        pre {
            granularity > 1 && granularity <= windowSize: "invalid granularity"
            windowSize / granularity * granularity == windowSize: "windowSize not-divisible by granularity"
        }
        post {
            UInt64(self.pairObservations.length) == granularity: "pairObservations array not initialized"
        }

        self.windowSize = windowSize
        self.granularity = granularity
        self.periodSize = windowSize / granularity
        self.isStableswap = isStableswap
        self.pairAddr = isStableswap ?
            StableSwapFactory.getPairAddress(token0Key: tokenAKey, token1Key: tokenBKey) ?? panic("non-existent stableswap-pair") :
            SwapFactory.getPairAddress(token0Key: tokenAKey, token1Key: tokenBKey) ?? panic("non-existent pair")

        let pairPublicRef = getAccount(self.pairAddr).getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath).borrow()
            ?? panic("cannot borrow reference to PairPublic")
        let pairInfo = pairPublicRef.getPairInfo()
        self.token0Key = pairInfo[0] as! String
        self.token1Key = pairInfo[1] as! String
        let reserve0 = pairInfo[2] as! UFix64
        let reserve1 = pairInfo[3] as! UFix64
        assert(reserve0 * reserve1 != 0.0, message: "There's no liquidity in the pair")

        self.pairObservations = []
        var i: UInt64 = 0
        while (i < granularity) {
            self.pairObservations.append(Observation(t: 0.0, p0Scaled: 0, p1Scaled: 0))
            i = i + 1
        }
    }
}
```

## Flashloan

### Flashloan Interfaces

```javascript
/// interface in SwapInterfaces.cdc
/// Before using the flashloan you need to first implement this interface and plugin customized logic (see example below)

pub resource interface FlashLoanExecutor {
    /// @params: User-definited extra data passed to executor for further auth/check/decode
    pub fun executeAndRepay(loanedToken: @FungibleToken.Vault, params: {String: AnyStruct}): @FungibleToken.Vault
}
```

### Example usage

```javascript
// Example_FlashloanLiquidation.cdc

import FungibleToken from 0xFungibleTokenAddr
import SwapConfig from 0xSwapConfigAddr
import SwapFactory from 0xSwapFactoryAddr
import SwapInterfaces from 0xSwapInterfacesAddr

pub contract Example_FlashloanLiquidation {
    // Specific address to receive flashloan-liquidation profits, used as auth purposes
    pub let profitReceiver: Address

    /// Implement the flashloan interface
    pub resource FlashloanExecutor: SwapInterfaces.FlashLoanExecutor {
        pub fun executeAndRepay(loanedToken: @FungibleToken.Vault, params: {String: AnyStruct}): @FungibleToken.Vault {
            pre {
                params.containsKey("profitReceiver") && ((params["profitReceiver"]! as! Address) == Example_FlashloanLiquidation.profitReceiver): "not-authorized caller"
            }

            /* 
                Do magic - custom logic goes here. E.g.:
                 - 0. Flashloan request $USDC from FUSD/USDC pool (in `do_flashloan.transaction.cdc`)
                 - 1. Liquidate underwater borrower by repaying borrowed $USDC and grab borrower's collateralized $Flow
                 - 2. Swap $Flow -> $USDC through IncrementSwap (cannot use flashloan-ed pool then) or BloctoSwap
                 - 3. Repay {flashloan-ed $USDC + fees} back to FUSD/USDC pool and keep remaining $USDC as profit
            */

            // TODO: plugin detailed example here
            let amountIn = loanedToken.balance

            // TODO: plugin detailed example here
            /// amountOut = amountIn x (1 + fee%)
            let amountOut = amountIn * (1.0 + UFix64(SwapFactory.getFlashloanRateBps()) / 10000.0) + SwapConfig.ufix64NonZeroMin

            // TODO: modify this
            return <-loanedToken
        }
    }

    init(profitReceiver: Address) {
        self.profitReceiver = profitReceiver

        // Set up FlashLoanExecutor resource
        let pathStr = "swap_flashloan_executor_path"
        let executorPrivatePath = PrivatePath(identifier: pathStr)!
        let executorStoragePath = StoragePath(identifier: pathStr)!
        destroy <-self.account.load<@AnyResource>(from: executorStoragePath)
        self.account.save(<- create FlashloanExecutor(), to: executorStoragePath)
        self.account.link<&{SwapInterfaces.FlashLoanExecutor}>(executorPrivatePath, target: executorStoragePath)
    }
}
```

```javascript
/// do_flashloan.transaction.cdc - tx that triggers flashloan from a SwapPair

import FungibleToken from 0xFungibleTokenAddr
import SwapConfig from 0xSwapConfigAddr
import SwapFactory from 0xSwapFactoryAddr
import SwapInterfaces from 0xSwapInterfacesAddr

/*
    E.g.: Flashloan request only $USDC from FUSD/USDC pool
*/
transaction(pairAddr: Address, requestedVaultType: Type, requestedAmount: UFix64) {
    prepare(signer: AuthAccount) {
        let pairRef = getAccount(pairAddr).getCapability<&{SwapInterfaces.PairPublic}>(SwapConfig.PairPublicPath).borrow()
            ?? panic("cannot borrow reference to PairPublic")

        // TODO: add additional args? and generalize this transaction
        let args: {String: AnyStruct} = {
            "profitReceiver": signer.address
        }
        let executorCap = signer.getCapability<&{SwapInterfaces.FlashLoanExecutor}>(/private/swap_flashloan_executor_path)
        pairRef.flashloan(executorCap: executorCap, requestedTokenVaultType: requestedVaultType, requestedAmount: requestedAmount, params: args)
    }
}
```


# Token Listing

Please note that as a permisssionless DEX (Decentralized Exchange) there's no "official listing" - anyone can import custom tokens directly on the Swap UI.

But for projects who want to include tokens into Swap's default dropdown menu - for more exposure (brand awareness and token logo, etc.) and make the token more easily accessible to users, please:

1. Create a pull request to this community-curated tokenlist repo on Flow: <https://github.com/FlowFans/flow-token-list>, a sample pr can be found [here](https://github.com/FlowFans/flow-token-list/commit/f445dd781023d0d83ec79d1be696b098d81f0518).
2. Fill in this [form](https://forms.gle/Ba61PPD2eHWocLCg6) and tell us in discord.&#x20;


# Security

#### 📔 Audited by Dapper Labs Internally (deployed before Flow permissionless deployment)

#### **🐛Bug bounty:** <https://docs.increment.fi/miscs/bug-bounty>&#x20;


# Decentralized Money Market

{% hint style="info" %}
**Increment Earn** is a pool-based, algorithmically-set interest rate, decentralized money market for fungible tokens on Flow blockchain. It aggregates user supplied funds into smart contracts, any deposited fungible tokens are also used as collaterals for borrowing other fungible tokens.&#x20;
{% endhint %}

<https://app.increment.fi/dashboard>


# User Guidance

## 1. Connect Wallet

The first step is to connect the app with a wallet to use the money market. In this guidance we’ll go ahead with BloctoWallet. It also supports to connect with LilicoWallet.

![](https://lh5.googleusercontent.com/aj-YOuVCeLjCY0XqCNC2jRKVBzveoVZcEixqPkYFLBeMCnWuizFO5Za-ZapYT325Q56eRYb0z0ohBrYfC5l8BDpIBA1W_uhsRQDMt5EVBkSvWZ6mCiXl92WhScZLwbPsEWtK2Kpc08zXSSyrgQ)

BloctoWallet requires your email to sign in/register, a one time passcode will be sent to your email. If you’re a frequent Blocto user, it might also automatically connect.

![](https://lh5.googleusercontent.com/hRRKAPjiji-t_fJDQnColdb-XEjNn0iXnfAEAuDS6GR86PiNWXkSjaXezyaWWcRL0rgAqJDmZs_UtugIAiQYHwXuFrR8U-MyLH3ldbZ3EZzsm7NLCOz9yeRXXAqNP1LQCeKpfroJPYp5-MFg_w)

## 2. Operations

### 2.1. Supply (Deposit)

Choose the token market (currently FLOW, FUSD, USDC & BLT are available) you want to deposit into, clicking <mark style="color:blue;">'Supply'</mark> button and then approve the transaction:

<div align="left"><img src="https://lh5.googleusercontent.com/6Lde18MNzw3vzXMwpsTEllMZ0FppoP5KI9ciLt_SOHTKcWccvp8Jw5-BH9Tg0BpTfaIbsFqPty-mjwFv2esnmi3VWWVLTDX2EFIK1d0hFAQzZuYaIC0yWaHnPWYyk2_oc8xn8w34GwVOiNwjBQ" alt=""></div>

### 2.2. Borrow

Supplied funds can be used as collaterals to borrow other fungible tokens. Let’s take the FLOW token as an example:

![](https://lh6.googleusercontent.com/JEgx2WpD4sUg_joMDbxBiZ3KL0Mh5yECUr4p4JFYfXcFvYdQZtVmuSAkrqdAlvIDAqKa5uwGZ8m_Zr4U5S0w13AOjMw1EhsNtbSog1vZdSlj3ppIAlQmEKoFEsMbI4J5TeksLjs6laD8yGy9tQ)

Click '<mark style="color:blue;">Safe Max</mark>' to automatically fill in the borrow Amount so that only <mark style="color:blue;">60%</mark> of the maximum borrow limit is used. You can manually edit that value, but just keeping in mind that the higher the percentage of borrow limit is used, the closer to liquidation the account is.&#x20;

Once borrowed, the page status will change and show your <mark style="color:blue;">position status</mark>, <mark style="color:blue;">net apr</mark> and the supply/borrow <mark style="color:blue;">balance</mark>.

![](https://lh4.googleusercontent.com/0Q2nr-IWZLzvipuyhyNCnBUrhlY16xqI6kXirHkqu4Y4IU2S4uwE-HQ35bBiEBHUkGAOFh2UsK1rU7hnbAhVHTFMz9AxdyWKA44C8AxyG67uD3I8k1mSEx6mjUNeEkxncp5JjjdeKiEhR2e7CQ)

In this example the repay button is <mark style="color:blue;">greyed</mark> out because the user has no borrow position that needs to be repaid.

### 2.3. Repay

Lower the borrow limit percentage by repaying back borrowed amount plus interest. Click <mark style="color:blue;">'Repay'</mark> button and switch to the 'Repay' card to perform the transaction:

![](https://lh5.googleusercontent.com/IA55A8hRApBj8vzWSk2PLayXaSk7jmjsjG9hJB53KLS7mbTkKXEkMVL3oN1wvyyDv8HnludGIlnlM9yEdTPhCcbbpPHbYcvZQuMxTlnhvn6hEt2IlVjodmGldzRsSTsqqfbJRZgitap1frX9ig)

### 2.4. Redeem (Withdraw)

Withdraw the supplied assets as well as generated yields by clicking <mark style="color:blue;">'Redeem'</mark> button and switch to the 'Redeem' card:

![](https://lh6.googleusercontent.com/eV1it4cdo3HQGBjGP76AiiW2xhBWAcjTWuy6G-LDaOcY4c3CYCK3HdqSEQactXFOSQCNfzEhS-aPz5bPZNNFK4K7SoCChBdi9NNZC2qQpHs6JsH8VoOFL8IWlEI9XaXW81NY3a4Gnil5Po37aw)

Still, the 'Safe Max' label is to protect the account from liquidation and automatically fill in the redeemed amount, which can be manually modified.

## 3. Understand Market Data

The <mark style="color:green;">'/Markets'</mark> page exposes global statistics like total TVL, number of suppliers and borrowers, as well as per-market data like market liquidity, supply APR and borrow APR, etc.:

![](https://lh3.googleusercontent.com/hXZ4Zf00W4WsMkNK9bq5JLz_bbuVqVZ5Gco1KIdpcPxQH_cVQKwIZgSp4fSAn_opkMWmMqn0yzGRBoiHJ-95knqnAsOoE8kpfY2mtsdAYLsny9IgYNqAwxKRtGN5xPlLE-p3okEFDeBvtbmYrg)

Further market parameters such as InterestRateModel, Collateral Factor, etc. can be viewed by clicking into the asset list:

![](https://lh6.googleusercontent.com/s1KKKGig4uJbFX4cvTdvBFP4BtqM8CeFUE7pc9qq_eNTEsgNsAGnt66aSRRHp8jurNm0R_Zp554MiYaCKpgRzp6Xj6YiXH-TXfEiRwhp6TdsTryGrYfbdlZwq4YpZM08T7FCElM_TAKM1IpBYw)

## 4. Tutorial by Flowverse

<https://twitter.com/flowverse_/status/1541268110267023366>


# Deployment Addresses

### Mainnet

<table><thead><tr><th width="260.3333333333333">Contract</th><th width="228">Address</th><th>Comment</th></tr></thead><tbody><tr><td>LendingError, LendingConfig, LendingInterfaces </td><td><a href="https://www.flowdiver.io/account/0x2df970b6cdee5735">0x2df970b6cdee5735</a></td><td>Constants, hepers, interfaces</td></tr><tr><td>LendingOracle</td><td><a href="https://www.flowdiver.io/account/0x72d3a05910b6ffa3">0x72d3a05910b6ffa3</a></td><td>Price oracles for lending markets</td></tr><tr><td>LendingComptroller</td><td><a href="https://www.flowdiver.io/account/0xf80cb737bfe7c792">0xf80cb737bfe7c792</a></td><td>Market configuration; safety auditing before applying side effects</td></tr><tr><td>TwoSegmentsInterestRateModel</td><td><a href="https://www.flowdiver.io/account/0xd57ea11ec725e6a3">0xd57ea11ec725e6a3</a></td><td>InterestRateModel for stablecoins</td></tr><tr><td>TwoSegmentsInterestRateModel</td><td><a href="https://www.flowdiver.io/account/0x38f9a6fc697e5cf9">0x38f9a6fc697e5cf9</a></td><td>InterestRateModel for non-stables</td></tr><tr><td>LendingAprSnapshot</td><td><a href="https://www.flowdiver.io/account/0x5da615e7385f307a">0x5da615e7385f307a</a></td><td>Onchain apr sampling data of each supported market</td></tr><tr><td>LendingPool</td><td><a href="https://www.flowdiver.io/account/0x7492e2f9b4acea9a">0x7492e2f9b4acea9a</a></td><td>Smart contract pool for FungibleToken market <code>Flow</code></td></tr><tr><td>LendingPool</td><td><a href="https://www.flowdiver.io/account/0x90f55b24a556ea45">0x90f55b24a556ea45</a></td><td>Smart contract pool for FungibleToken market <code>FUSD</code></td></tr><tr><td>LendingPool</td><td><a href="https://www.flowdiver.io/account/0x8334275bda13b2be">0x8334275bda13b2be</a></td><td>Smart contract pool for FungibleToken market <code>USDC</code>(to-be-deprecated after Crescendo mainnet upgrade)</td></tr><tr><td>LendingPool</td><td><a href="https://www.flowdiver.io/account/1113980ca45d1d37">0x1113980ca45d1d37</a></td><td>Smart contract pool for FungibleToken market <code>USDCf</code>(a wrapped USDC token fully backed by USDC)</td></tr><tr><td>LendingPool</td><td><a href="https://www.flowdiver.io/account/0x67539e86cbe9b261">0x67539e86cbe9b261</a></td><td>Smart contract pool for FungibleToken market <code>BLT</code></td></tr><tr><td>LendingPool</td><td><a href="https://www.flowdiver.io/account/0x44fe3d9157770b2d">0x44fe3d9157770b2d</a></td><td>Smart contract pool for FungibleToken market <code>stFlow</code></td></tr></tbody></table>

### Testnet

| Contract                                       | Address                                                                       | Comment                                                            |
| ---------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| LendingError, LendingConfig, LendingInterfaces | [0x8bc9e24c307d249b](https://testnet.flowdiver.io/account/0x8bc9e24c307d249b) | Constants, hepers, interfaces                                      |
| LendingOracle                                  | [0x7745157792470296](https://testnet.flowdiver.io/account/0x7745157792470296) | Price oracles for lending markets                                  |
| LendingComptroller                             | [0xc15e75b5f6b95e54](https://testnet.flowdiver.io/account/0xc15e75b5f6b95e54) | Market configuration; safety auditing before applying side effects |
| TwoSegmentsInterestRateModel                   | [0x23031fd14bb0f21b](https://testnet.flowdiver.io/account/0x23031fd14bb0f21b) | InterestRateModel for stablecoins                                  |
| TwoSegmentsInterestRateModel                   | [0xcc4e949596cf8ced](https://testnet.flowdiver.io/account/0xcc4e949596cf8ced) | InterestRateModel for non-stables                                  |
| LendingPool                                    | [0x8aaca41f09eb1e3d](https://testnet.flowdiver.io/account/0x8aaca41f09eb1e3d) | Smart contract pool for FungibleToken market `Flow`                |
| LendingPool                                    | [0x97d2f3b55c6a6a75](https://testnet.flowdiver.io/account/0x97d2f3b55c6a6a75) | Smart contract pool for FungibleToken market `USDC`                |
| LendingPool                                    | [0x9e324d8ae3cbd0f0](https://testnet.flowdiver.io/account/0x9e324d8ae3cbd0f0) | Smart contract pool for FungibleToken market `FUSD`                |


# Interest Rate Model

{% hint style="info" %}
The interest rate for each market is determined dynamically, purely based on supply and demand of that market. Interest is calculated and accrued on a per-block basis, with an average of \~1.25s mainnet [blocktime](https://docs.onflow.org/cadence/measuring-time/#time-on-the-flow-blockchain) and \~0.8s testnet blocktime as of June 2023.
{% endhint %}

### Interest Rate Model for {Flow, stFlow, BLT, USDC, FUSD} markets&#x20;

<table><thead><tr><th width="150">baseRate</th><th width="150">criticalRate</th><th width="150">criticalPoint</th><th width="150">baseSlope</th><th width="150">jumpSlope</th><th>reserveFactor</th></tr></thead><tbody><tr><td>0.1%</td><td>10.1%</td><td>80%</td><td>0.125</td><td>3.5</td><td>10%</td></tr></tbody></table>

<figure><img src="/files/qHumXpX6dTg3hd1pV0Pg" alt=""><figcaption></figcaption></figure>

Users will be charged interests for borrowing fungible token assets. The borrow interest rate is algorithmically-set based on supply and demand of the asset - which is reflected by the asset pool utilization rate.&#x20;

### Utilization Rate

$$
poolUtilizationRate = \frac{poolBorrows}{poolBorrows + poolCash - poolReserve}
$$

### Borrow Interest Rate

A critical point (80%) exists in the borrow interest rate model:&#x20;

* When utilization rate is below the critical point, a flatter slope is applied
* Once utilization rate exceeds the critical point, the slope becomes much steeper - This incentives borrowers to pay back the borrowed assets while at the same also incentives suppliers to deposit assets to earn a high APR.&#x20;

$$
borrowInterestRate=\left{
\begin{array}{ll}
baseRate\ +\ baseSlope\cdot utilRate, & \mbox{utilRate$\<criticalPoint$}\\
jumpSlope\cdot\left(utilRate-criticalPoint\right)+criticalRate, & \mbox{utilRate$\ge criticalPoint$}
\end{array}
\right.
$$

### Supply Interest Rate

Supply interest rate is inferred from borrow interest rate after deducting the fraction goes to the pool reserve:

$$
supplyInterestRate = (1 - reserveFactor) \cdot utilRate \cdot borrowInterestRate
$$

### Reserve

Each asset pool maintains a FungibleToken Vault as pool reserve, whose balance comes from a fraction of generated interests, determined by **reserveFactor**. Reserve serves the purpose of incentivization and risk mitigation, such as protection against smart contracts exploits, oracle attacks, emergency shutdown, etc.&#x20;


# Market Parameter

### Flow

Proposed parameters for FlowToken:

| Parameter               | Value      |
| ----------------------- | ---------- |
| Collateral Factor       | 80.0%      |
| Supply Cap              | 30,000,000 |
| Borrow Cap              | 15,000,000 |
| Liquidation Incentive   | 10.0%      |
| Liquidation CloseFactor | 0.5        |

### stFlow

Proposed parameters for stFlow:

| Parameter               | Value      |
| ----------------------- | ---------- |
| Collateral Factor       | 75.0%      |
| Supply Cap              | 30,000,000 |
| Borrow Cap              | 15,000,000 |
| Liquidation Incentive   | 10.0%      |
| Liquidation CloseFactor | 0.5        |

### USDC

Proposed parameters for USDC:

| Parameter               | Value |
| ----------------------- | ----- |
| Collateral Factor       | 90.0% |
| Supply Cap\*            | 0     |
| Borrow Cap\*            | 0     |
| Liquidation Incentive   | 10.0% |
| Liquidation CloseFactor | 0.5   |

### USDCf

Proposed parameters for USDCf:

| Parameter               | Value     |
| ----------------------- | --------- |
| Collateral Factor       | 90.0%     |
| Supply Cap              | 8,000,000 |
| Borrow Cap              | 6,000,000 |
| Liquidation Incentive   | 10.0%     |
| Liquidation CloseFactor | 0.5       |

\* USDC on Cadence will be deprecated after Crescendo mainnet upgrade and its contract would break by then. USDC market will be entering deprecation mode that only repaying / withdrawing is allowed.

\* USDCf on Cadence is a wrapped USDC token, which is fully backed by USDC on Ethereum and will keep working before & after Crescendo mainnet upgrade. Learn more [here](https://forum.flow.com/t/stablecoin-stability-through-crescendo-and-erc-20-standards-on-flow/6341).

### FUSD

Proposed parameters for FUSD:

| Parameter               | Value |
| ----------------------- | ----- |
| Collateral Factor       | 90.0% |
| Supply Cap\*            | 0     |
| Borrow Cap\*            | 0     |
| Liquidation Incentive   | 5.0%  |
| Liquidation CloseFactor | 0.5   |

\* FUSD's supply/borrow cap has been lowered to 0 on July 17 2023, <mark style="color:blue;">making this market only redeemable and repayable, but not suppliable or borrowable any more</mark>. This is a preparation for sunsetting this market as FUSD is being obsoleted due to the Prime Trust [issue](https://www.theblock.co/post/236097/nevada-regulator-says-prime-trust-cant-meet-all-client-withdrawals). &#x20;

### BLT

Proposed parameters for BloctoToken:

| Parameter               | Value   |
| ----------------------- | ------- |
| Collateral Factor       | 33.0%   |
| Supply Cap              | 100,000 |
| Borrow Cap              | 100,000 |
| Liquidation Incentive   | 20.0%   |
| Liquidation CloseFactor | 0.5     |


# Liquidation

{% hint style="info" %}
A borrower's account goes underwater and is subject to liquidation when the total borrows cross all markets exceeded the account borrow limit, which is calculated based on borrower's collateralized assets and per-market collateralFactor.

Anyone can liquidate underwater accounts by repaying back borrowed assets on behalf of the borrower. As return, the liquidator gets back ("purchases") the borrower's collateral asset at current market price with a discount as incentive.

From the borrower's point of view the corresponding collaterals are "slashed" and transferred to the liquidator. The maximum amount of collaterals to be "slashed" is capped by the parameter closeFactor, ranging from 0.0 to 1.0. CloseFactor is a metric to protect underwater borrowers from losing all of the collaterals when liquidation occurs.
{% endhint %}

### Version 1.0 (Current)

To enrourage the community to participate in the liquidation process, a simple reference implementation of the liquidation bot will be open sourced for easy usage and further modification. We also encourage developers to build third party liquidation bots - taking part in the liquidation process is not only profitable but also keeps the money market system safe and healthy.

### Version 2.0

Version 1.0 liquidators have to hold certain amount of capital and may need to periodically rebalance their holdings. To further lower the burden of liquidation process, flashloan is on our agenda. Increment Labs is actively researching and developing flow-based flashloan infrastructure, the plan is to build and release a flashloan-based liquidation bot 2.0 in near future.&#x20;


# Governance

Increment **begins with** centralized admin control of the money market protocol, including:

* Tuning InterestRateModel
* Running decentralized oracle nodes
* Configuring per-market risk parameters such as data source weight, collateralFactor, borrowCap, liquidationPenalty, etc.
* However, admin has no right to transfer or drain pooled fungible tokens.

The goal is to **finally grant full community control** (DAO) of:

* The ability to add / suspend a fungible token market
* The ability to update InterestRateModel for each market
* The ability to vote, whitelist, and incentive outer oracle nodes which maybe run by other projects, community developers, etc.
* The ability to change per-market risk parameters
* The ability to reduce market reserve and determine its usage

We believe that move fast in the first place while being transparent to reach **progressive decentralization** is the best practice.&#x20;


# Security

#### 📔 Audited by Dapper Labs Internally (deployed before Flow permissionless deployment)

#### 📔 Audited by [Oak Security](https://www.oaksecurity.io/): => [Link](https://increment-audit.s3.us-west-1.amazonaws.com/Audit+Report+-+Increment+Finance.pdf)&#x20;

#### **🐛Bug bounty:** <https://docs.increment.fi/miscs/bug-bounty>


# Decentralized Price Feed (Oracle)

{% hint style="info" %}
We've built and been maintaining a native price oracle service on the Flow blockchain that combines both decentralization and practicability. The service may also serve as public goods for other projects building on Flow blockchain.&#x20;
{% endhint %}

<https://app.increment.fi/oracle>


# Architecture

{% hint style="info" %}
Frontend demonstration: <https://app.increment.fi/oracle>
{% endhint %}

## Overall architecture

### Mainnet:

**Basic architecture**: *Multiple whitelisted-nodes* independently fetching price data from *multiple data* *sources* to guard against potential node failure. Then the medianizer contract aggregates and picks the median data reported from whitelisted nodes.&#x20;

<figure><img src="/files/zyV2ul3TT9NsA71a4Hgo" alt=""><figcaption></figcaption></figure>

There are two ways for nodes to perform price aggregation: median method and weighted-average method.

* **Median**: When there are enough price origins, taking the median value can improve security more effectively.
* **Weighted-average**: Based-on trading volume, liquidity depth, exchange reputation, etc., price will be fetch from different exchanges for different fungible tokens, applied with different weights.

#### **Flow/USD** price feed&#x20;

It has 8 origins currently and is applied with the ***median*** method based on <https://www.coingecko.com/en/coins/flow#markets>:

* Kraken [Flow/USD](https://pro.kraken.com/app/trade/FLOW-USD) &#x20;
* Coinbase [Flow/USD](https://pro.coinbase.com/trade/FLOW-USD)
* Binance [Flow/USDT](https://www.binance.com/en/trade/FLOW_USDT) x (Latest USDT/USD On-Chain PriceOracle data)
* OKX [Flow/USDT](https://www.okx.com/trade-spot/flow-usdt) x (Latest USDT/USD On-Chain PriceOracle data)
* Gateio [Flow/USDT](https://www.gate.io/zh/trade/FLOW_USDT) x (Latest USDT/USD On-Chain PriceOracle data)
* Huobi [Flow/USDT](https://www.huobi.com/en-us/exchange/flow_usdt) x (Latest USDT/USD On-Chain PriceOracle data)
* KuCoin [Flow/USDT](https://www.kucoin.com/trade/FLOW-USDT) x (Latest USDT/USD On-Chain PriceOracle data)
* Bybit [Flow/USDT](https://www.bybit.com/en-US/trade/spot/FLOW/USDT) x (Latest USDT/USD On-Chain PriceOracle data)

#### **USDT/USD** price feed

It has 3 origins and is applied with the ***weighted-average*** method base on <https://www.coingecko.com/en/coins/tether#markets>:

* Kraken [USDT/USD](https://pro.kraken.com/app/trade/usdt-usd) - 50%
* Coinbase [USDT/USD](https://pro.coinbase.com/trade/USDT-USD) - 35%
* Bitfinex [USDT/USD](https://trading.bitfinex.com/t/UST:USD?type=exchange) - 15%\*

*\* There're concerns and rumors about Bitfinex & Tether manipulation / non-transparency. So although Bitfinex's USDT/USD volume is on par with Coinbase's, it only has a weight of 15%.*

#### **Stablecoins'** price feed

* **USDC/USD** price feed has 5 price origins and is applied with the ***median*** method based on <https://www.coingecko.com/en/coins/usd-coin#markets>:

  *(\* According to the recent SBV's collapse and Circle is* [*holding*](https://twitter.com/circle/status/1634391505988206592) *a % of cash reserve in SBV, so USDC is not fixed to 1.0 face value any more since 03/11/2023.)*

  * The "fair-value" 1.0
  * Kraken [USDC/USD](https://pro.kraken.com/app/trade/USDC-USD)
  * (Bybit [USDC/USDT](https://www.bybit.com/en-US/trade/spot/USDC/USDT)) x (Latest USDT/USD On-Chain PriceOracle data)
  * (Binance [USDC/USDT](https://www.binance.com/en/trade/USDC_USDT)) x (Latest USDT/USD On-Chain PriceOracle data)
  * (OKX [USDC/USDT](https://www.okx.com/trade-spot/usdc-usdt)) x (Latest USDT/USD On-Chain PriceOracle data)
* **FUSD/USD** price feed is applied with a *constant* 1.0. (FUSD is under-deprecation on Flow, and there's very little exposure to FUSD.)

#### **Other fungible tokens' price feed**:

* **BLT/USD** price feed is applied with the ***weighted-average*** method based on <https://www.coingecko.com/en/coins/blocto-token#markets>:
  * Gateio [BLT/USDT](https://www.gate.io/zh/trade/BLT_USDT) x (Latest USDT/USD On-Chain PriceOracle data) - 67%
  * Mexc [BLT/USDT](https://www.mexc.com/exchange/BLT_USDT) x (Latest USDT/USD On-Chain PriceOracle data) - 33%
  * \*To on-board BLT token's price from Bloctoswap, it needs to integrate with care.
* **stFlow/USD** price feed is computed with on-chain data by:
  * &#x20;(stFlow/Flow taken from LiquidStaking Contract) x (Flow/USD On-Chain PriceOracle data)

### Testnet:

**Basic architecture**: A *single node* fetching from *multiple* data sources. (Very much close to the mainnet's arch, but to save our resources and costs.)

### Emulator:

**Basic architecture**: A *single node* SimpleOracle fetching from a *single data* source (Coingecko api) is used on emulator for local bootstrapping and testing.&#x20;

Price data is periodically fetched, and it gets updated whichever below conditions happen first:

* `windowSize`: e.g. 1200 - every 1,200 seconds
* `deviation`: e.g. 0.01 - once Δ { fetchedData, lastData } > 0.01 \* lastData

## Contract architecture

<figure><img src="/files/H4JFor8P6wzuKz0CQL65" alt=""><figcaption></figcaption></figure>

For each different type of price feed, a separate `PriceOracle` contract is deployed to support it.&#x20;

The PriceOracle contract defines two whitelists and two resources: `PriceReader` and `PriceFeeder`. PriceReader resource holder has the ability to access reported data as long as it's also in the reader whitelist. PriceFeeder resource holder has the ability to post price data and influence the medianized onchain price data as long as it's also in the feeder whitelist.

<figure><img src="/files/y4JOVtFUfd7zdNPrAxnn" alt=""><figcaption></figcaption></figure>

* For developers to use the on-chain price data in your Cadence contracts there's no barrier to apply for the reader whitelist - we've made it **free and public** through the PublicPriceOracle contract with some Chainlink-like APIs. Please read [Using Price Feeds](/protocols/decentralized-price-feed-oracle/using-price-feeds) for more details.&#x20;
* For institutions and partners interest in joining node runners & feeder whitelist to provide more decentralized price feeds on flow, welcome to contact us.


# Deployment Addresses

### Mainnet

| Contract                      | Address                                                                   | Comment                                                                                                                                   |
| ----------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| PublicPriceOracle             | [0xec67451f8a58216a](https://www.flowdiver.io/account/0xec67451f8a58216a) | <p><strong>Onchain price feeds free-to-use.</strong> </p><p><strong>Devs / projects only need to import and check this one.</strong> </p> |
| OracleConfig, OracleInterface | [0xcec15c814971c1dc](https://www.flowdiver.io/account/0xcec15c814971c1dc) | Paths & library functions, Public Interfaces                                                                                              |
| PriceOracle                   | [0xe385412159992e11](https://www.flowdiver.io/account/0xe385412159992e11) | `Flow / USD`                                                                                                                              |
| PriceOracle                   | [0x07e2f8fc48632ece](https://www.flowdiver.io/account/0x07e2f8fc48632ece) | `USDT / USD`                                                                                                                              |
| PriceOracle                   | [0x11b69dcfd16724af](https://www.flowdiver.io/account/0x11b69dcfd16724af) | `BLT / USD`                                                                                                                               |
| PriceOracle                   | [0xf5d12412c09d2470](https://www.flowdiver.io/account/0xf5d12412c09d2470) | `USDC / USD`                                                                                                                              |
| PriceOracle                   | [0x1a9caf561de25a86](https://www.flowdiver.io/account/0x1a9caf561de25a86) | <p><code>FUSD / USD</code></p><p>(Fixed to <code>1.0</code>)</p>                                                                          |
| PriceOracleStFlow             | [0x031dabc5ba1d2932](https://www.flowdiver.io/account/0x031dabc5ba1d2932) | stFlow / USD                                                                                                                              |

### Testnet

| Contract                      | Address                                                                       | Comment                                                           |
| ----------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| PublicPriceOracle             | [0x8232ce4a3aff4e94](https://testnet.flowdiver.io/account/8232ce4a3aff4e94)   | Onchain price feeds free-to-use.                                  |
| OracleConfig, OracleInterface | [0x2a9b59c3e2b72ee0](https://testnet.flowdiver.io/account/0x2a9b59c3e2b72ee0) | Constants, interfaces                                             |
| PriceOracle                   | [0xcbdb5a7b89c3c844](https://testnet.flowdiver.io/account/0xcbdb5a7b89c3c844) | `Flow / USD`                                                      |
| PriceOracle                   | [0x6d692450d591524c](https://testnet.flowdiver.io/account/0x6d692450d591524c) | `USDT / USD`                                                      |
| PriceOracle                   | [0x2d766f00eb1d0c37](https://testnet.flowdiver.io/account/0x2d766f00eb1d0c37) | `BLT / USD`                                                       |
| PriceOracle                   | [0xc911d6ddfae70ce8](https://testnet.flowdiver.io/account/0xc911d6ddfae70ce8) | <p><code>USDC / USD</code> </p><p>(Fixed to <code>1.0</code>)</p> |
| PriceOracle                   | [0x3b220a3372190656](https://testnet.flowdiver.io/account/0x3b220a3372190656) | <p><code>FUSD / USD</code></p><p>(Fixed to <code>1.0</code>)</p>  |
| PriceOracle                   | [0xdad0aaa285a25413](https://testnet.flowdiver.io/account/0xdad0aaa285a25413) | <p><code>BUSD / USD</code></p><p>(Fixed to 1.0)</p>               |
| PriceOracle                   | [0x24650d6246d4176c](https://testnet.flowdiver.io/account/0x24650d6246d4176c) | `Test / USD` without reader whitelist                             |


# Using Price Feeds

### Get all supported price feeds and their addresses

```javascript
import PublicPriceOracle from 0xAddress

// oracleAddress => oracleTag
pub fun main(): {Address: String} {
    return PublicPriceOracle.getAllSupportedOracles()
} 
```

Sample result:

```javascript
{
    0xf5d12412c09d2470	:    "USDC/USD"
    0xe385412159992e11	:    "FLOW/USD"
    0x1a9caf561de25a86	:    "FUSD/USD"
    0x031dabc5ba1d2932	:    "stFlow/USD"
    0x11b69dcfd16724af	:    "BLT/USD"
    0x07e2f8fc48632ece	:    "USDT/USD"
}
```

### Get latest result and update time

```javascript
import PublicPriceOracle from 0xAddress

pub fun main(oracle: Address): [UFix64] {
    let lastResult = PublicPriceOracle.getLatestPrice(oracleAddr: oracle)
    let lastBlockNum = PublicPriceOracle.getLatestBlockHeight(oracleAddr: oracle)
    // Get block timestamp does not always work: the # of recent blocks cached and servicable are depending on execution nodes. 
    let lastTimestamp = getBlock(at: lastBlockNum)?.timestamp
    return [
        lastResult,
        UFix64(lastBlockNum),
        lastTimestamp ?? 0.0
    ]
}
```

Sample result for "Flow/USD" price feed:

```javascript
[0.58717715, 57835057.00000000, 1690794621.00000000]
```

Note that:&#x20;

* The data is updated whichever condition is met first:
  * Deviation is beyond certain threshold (by default 0.5%)
  * A fixed window of time has passed (by default 2000 blocks)&#x20;
* Users of the PublicPriceOracle need to check the latest update time and handle the extreme condition if this data is too old.
* We recommend to use [blockHeight](https://developers.flow.com/cadence/language/environment-information#block-information), as the block timestamp is not accurate or not always retrievable: the number of recent blocks cached and servicable are depending on execution nodes.&#x20;

### DEX-based TWAP Price Oracle

Check examples [here](https://docs.increment.fi/protocols/decentralized-exchange/smart-contract-api#build-a-twap-oracle).


# Apply as Feeder

### \[Under construction]


# Liquidity Mining (Farm)

<https://app.increment.fi/farm>&#x20;


# Token Farm

Stake FungibleToken (e.g. LpToken) into a liquidity mining pool to earn (potential multiple) FungibleTokens as rewards.


# Deployment Addresses

### Mainnet

| Contract     | Address                                                                   | Comment                                                                                                                |
| ------------ | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| StakingError | [0x1b77ba4b414de352](https://www.flowdiver.io/account/0x1b77ba4b414de352) | Common error codes                                                                                                     |
| Staking      | [0x1b77ba4b414de352](https://www.flowdiver.io/account/0x1b77ba4b414de352) | Stake FungibleToken (e.g. LpToken) into a liquidity mining pool to earn (potential multiple) FungibleTokens as rewards |

### Testnet

| Contract     | Address                                                                       | Comment                                                                      |
| ------------ | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| StakingError | [0x26a1e94319e81a3c](https://testnet.flowdiver.io/account/0x26a1e94319e81a3c) | Common error codes                                                           |
| Staking      | [0x26a1e94319e81a3c](https://testnet.flowdiver.io/account/0x26a1e94319e81a3c) | Stake LpToken into a liquidity mining pool to earn FungibleTokens as rewards |


# NFT Farm

Stake NonFungibleToken (e.g. a Float) into a staking pool to earn (potential multiple) FungibleTokens as rewards.


# Deployment Addresses

### Mainnet

| Contract            | Address                                                                   | Comment                                                                                                                                                                                                                                                                       |
| ------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| StakingError        | [0x1b77ba4b414de352](https://www.flowdiver.io/account/0x1b77ba4b414de352) | Common error codes                                                                                                                                                                                                                                                            |
| StakingNFT          | [0x1b77ba4b414de352](https://www.flowdiver.io/account/0x1b77ba4b414de352) | Stake NonFungibleToken (e.g. a Float) into a staking pool to earn (potential multiple) FungibleTokens as rewards.                                                                                                                                                             |
| StakingNFTVerifiers | [0x1b77ba4b414de352](https://www.flowdiver.io/account/0x1b77ba4b414de352) | An extra verifier checks whether the given nft is allowed to stake into a farm pool. Use cases: e.g. All floats are stored in the same Collection, but logically they belong to different `FLOATEvents`. This contract is upgradable, with more  verifiers to be implemented. |

### Testnet

| Contract            | Address                                                                       |
| ------------------- | ----------------------------------------------------------------------------- |
| StakingError        | [0x44ef9309713e2061](https://testnet.flowdiver.io/account/0x44ef9309713e2061) |
| StakingNFT          | [0x44ef9309713e2061](https://testnet.flowdiver.io/account/0x44ef9309713e2061) |
| StakingNFTVerifiers | [0x44ef9309713e2061](https://testnet.flowdiver.io/account/0x44ef9309713e2061) |


# Liquid Staking

The easiest way to stake Flow without locking funds!

{% hint style="info" %}
Increment has developed and launched the first leading non-custodial **L**iquid **S**taking **P**rotocol (i.e. **LSP**) on Flow.

By allowing users to **earn staking rewards** and **enjoy unlocked liquidity** to **participate in Flow's DeFi** ecosystem *at the same time*, we believe that LSP creates huge new opportunities to the Flow network, node operators, stakers, and token holders as a whole.

LSP helps to *decentralize the network*, *ease the staking process* & *diversify the risks*, *release unlocked capital*, and create *more yield & composibility* opportunities.&#x20;

Just give an example here: there are currently \~ 719,000,000 `$flow` tokens locked in staking. If we were able to make 10% of these staked tokens liquid, we’ll have \~ $121 million worth of TVL to participate in Flow's DeFi ecosystem.
{% endhint %}

<https://app.increment.fi/staking>


# User Guidance

### 1. Connect Wallet

<figure><img src="/files/SopBtVAyOYT3UzDe4SR6" alt=""><figcaption></figcaption></figure>

It now supports 3 most widely-used wallets on Flow: Lilico (non-custodial), Blocto (custodial), and NuFi (non-custodial). More wallets will be intergrated in future.&#x20;

### 2. Stake

You'll receive `$stFlow` token which represents your staked position (along with any generated staking rewards) by staking in the `Stake` tab. Some notes below:

* The exchange rate of `$stFlow` against `$flow` starts at 1.0, and grows over time, so the amount of `stFlow` token to be received will be `<=` the input amount of `$flow`.
* `Swap from DEX` entry will pop up and give you a friendly notice if you can get more `$stFlow` by swapping on the AMM/DEX (*It sometimes happenes when people with a large staked position need instant redemption and swap back*).
* You may notice the `Epoch End Phase` warning below. Due to Flow's underlying staking mechanism, no staking operation will be allowed during epoch end phase (to be exact, it's called epoch setup & epoch commit, see [here](https://developers.flow.com/nodes/staking/schedule)), and it typically lasts several hours.

<figure><img src="/files/AgNgPZck0rkxvI44VVxI" alt=""><figcaption></figcaption></figure>

### 3. Unstake

There're 2 sections in the `Unstake` tab: request to unstake and withdrawal schedule table.

1. As explained above and in the [FAQ](https://docs.increment.fi/protocols/liquid-staking/faq), `$stFlow`'s grows over time and rewards are auto-compounded (there's no need to manually claim staking rewards), so you'll receive more `$flow` in redemption. Like traditional staking to a node, there's a 1\~2 epoch waiting time before `$flow` becomes withdrawable. If you need instant liquidity, consider to directly swap `$stFlow` to `$flow` on DEX. The entry `Instant unstake on DEX` is also provided for comparision and for the convenience of users.
2. Both matured and pending withdrawals are listed in the schedule table. You can check and come back to withdraw them whenever you like when they're matured.

<figure><img src="/files/aZKtkiuu2wJ9JOmWNAAe" alt=""><figcaption></figcaption></figure>

*(\*You can unstake at any time, even during Epoch End phase. Any unstaking requests performed in this period are cached and will be picked up and processed in the beginning of next epoch.)*

### 4. Migrate

`Migrate` is for existing delegators: if you’ve delegated to a node already, you do not need to unstake from the node, but instead you can “migrate” staked positions and receive `$stFlow` immediately, in 1 transaction.

Staked tokens & newly commited tokens are migratable, hover over:question:to see details. Furthermore:

* Any unclaimed rewards or unstaked tokens will be migrated along with staked and newly commited tokens, **in 1 click**.
* Any *new unstake request* will be *canceled* and then the position will be migrated, all **in 1 click**.

&#x20;         ![](/files/WO9nBFpi01H4YnrgPg8V)        ![](/files/Zp6AQavZHAIWh51SvKK5)&#x20;

There’re also ***restrictions*** on migratable positions:

* If the position has any *ongoing unstaking request*, it is ***temporarily*** non-migratable: you’ll have to wait for 1 epoch until the unstaking request becomes ‘unstaked’ and then come back to the '`Migrate'` tab.

  &#x20;                                         ![](/files/egB2eJcU1WHZ20OTOOVf)
* If the staked position has used [locked account](https://developers.flow.com/flow/core-contracts/locked-tokens) to handle staking (for example: Blocto), you ***have to unstake from locked account*** first. In the below example:
  * 5,000 Flow will be unstaked from locked account;
  * And any migratable (unclaimed rewards, unstaked, newly commited) amount will be migrated and you'll receive corresponding amount of `stFlow`;
  * Come back after 2 epoches, and you'll see 5,000 Flow being migratable.

<figure><img src="/files/7YwBb6iypKqxvypM1rsg" alt=""><figcaption></figcaption></figure>

* If you do have any ***unvested*** flow staked, the position is non-migratable.&#x20;

&#x20;                                              ![](/files/lT5jvqBqJA2jR8RaYB4P)

*(\*Note that during `Epoch End` phase, just as staking operations, migrate operations are also disabled.)*

### 5. Tutorial by Flowverse

<https://twitter.com/flowverse_/status/1587968924540612608>


# Deployment Addresses

### Mainnet

| Contract                                | Address                                                                   | Comment                                                                                                                                             |
| --------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| stFlowToken                             | [0xd6f80565193ad727](https://www.flowdiver.io/account/0xd6f80565193ad727) | A liquid (transferrable), interest-bearing fungible token, backed by the underlying staked `$Flow` and any generated staking rewards                |
| LiquidStakingError, LiquidStakingConfig | [0xd6f80565193ad727](https://www.flowdiver.io/account/0xd6f80565193ad727) | Error codes, constants, configurable paramaters                                                                                                     |
| LiquidStaking                           | [0xd6f80565193ad727](https://www.flowdiver.io/account/0xd6f80565193ad727) | Main entry points to the Liquid Staking Protocol, including public functions like `stake`, `unstake`, `migrate`, `cashoutWithdrawVoucher`, etc.     |
| DelegatorManager                        | [0xd6f80565193ad727](https://www.flowdiver.io/account/0xd6f80565193ad727) | Management of staked `$flow`, handling unstaking requests and delegation strategies, protocol epoch advancement and price update of `$stFlow` token |

### Testnet

<table><thead><tr><th width="247">Contract</th><th>Address</th></tr></thead><tbody><tr><td>stFlowToken</td><td><a href="https://testnet.flowdiver.io/account/0xe45c64ecfe31e465">0xe45c64ecfe31e465</a></td></tr><tr><td>LiquidStakingError, LiquidStakingConfig</td><td><a href="https://testnet.flowdiver.io/account/0xe45c64ecfe31e465">0xe45c64ecfe31e465</a></td></tr><tr><td>LiquidStaking</td><td><a href="https://testnet.flowdiver.io/account/0xe45c64ecfe31e465">0xe45c64ecfe31e465</a></td></tr><tr><td>DelegatorManager</td><td><a href="https://testnet.flowdiver.io/account/0xe45c64ecfe31e465">0xe45c64ecfe31e465</a> </td></tr></tbody></table>


# Use stFlow

### Coingecko

<https://www.coingecko.com/en/coins/liquid-staked-flow>&#x20;

###

### Trade / Swap stFlow to any other token

On [Swap](https://app.increment.fi/swap?in=A.d6f80565193ad727.stFlowToken\&out=A.1654653399040a61.FlowToken)

###

### Earn more yield in liquidity-incentive program

On <https://app.increment.fi/farm>

### Borrow / Lend stFlow & use as collaterals

On <https://app.increment.fi/markets>

### Buy NFT with stFlow

🔜 ...


# Protocol Overview


# stFlow token

### What is $stFlow?

$stFlow is a fungible token on Flow blockchain that represents a share of the total $flow tokens staked through liquid staking protocol, along with any generated staking rewards.

User will receive $stFlow tokens after staking $flow tokens in LSP (liquid staking protocol). As a kind of staking receipt, user can exchange $flow tokens and the earned rewards back through burning $stFlow.

The minting of $stFlow only happens when new staking occurs in LSP.&#x20;

### How is $stFlow quoted?

The latest $stFlow/$Flow price can be queried by protocol interface:

```
// 9.9913 &stFlow -> 10.0000 $flow
LiquidStaking.calcStFlowFromFlow(flowAmount: UFix64)

// 10.0000 $flow -> 9.9913 &stFlow
LiquidStaking.calcFlowFromStFlow(stFlowAmount: UFix64)
```

At the beginning of each new epoch, $stFlow price will be recalculated and this quote will not change during the whole epoch period.

The quotation of $stFlow is:

$$
$stFlow Price = \frac{\[$flow's TotalStaked] + \[EarnedRewards]}{\[$stFlow's TotalSupply]}
$$

It is not difficult to find that the price of $stFlow will continue to increase as new staking rewards accrued. At the epoch of creation, the price of 1 $stFlow is equal to 1 $flow.

Assume that the Apr of staking is 8%, and the reward is issued according to the $flow total staked:

$$
EarnedRewards = \frac{$flow's TotalSupply \* 0.08}{52}
$$

The price change of $stFlow over one year can be plotted:​

<figure><img src="/files/G5xGXigWg9OQTPC7sgHV" alt=""><figcaption></figcaption></figure>


# Protocol Epoch

### Epoch on Flow

An Epoch is a roughly week-long period that the flow-blockchain uses to manage node list and pay the staking rewards.

Regarding the underlying layer of epoch on flow, the following lists part of important points. Please see the [Epoch Documentation](https://developers.flow.com/nodes/staking/schedule) for deep explanations. &#x20;

<figure><img src="/files/P2ucWJwCnh7c3ZhBJmP8" alt=""><figcaption><p>Flow Epoch Schedule</p></figcaption></figure>

* In a Flow Epoch cycle，it is divided into two phases: Staking Auction Phase and Epoch Setup/Committed Phase.
* Staking Auction phase last for 6 days from Thursday to Wednesday (UTC). Users can stake / unstake during this phase.
* Epoch Setup\&Committed phase usually last for several hours. Users **cannot** stake / unstake at this short time, and need to wait for the new epoch start.
* After a Flow Epoch ends, the rewards are distributed and the next epoch will begin.

### Epoch of Liquid Staking Protocol

Compared with Flow Epoch, the liquid staking protocol also has its own Epoch, which we call the Protocol Epoch. This Epoch within the protocol will start a little later after the Flow Epoch starts. Specifically, after Flow distributes rewards and comes a new Epoch, the Protocol will start collecting rewards from all delegators (up to 50,000) within a short time window (1-10 minutes), and, when collection is done, the new $stFlow price will be calculated for the next whole week. At this point, the Protocol Epoch will be synced to the Flow Epoch (Protocol Epoch = Flow Epoch).

<figure><img src="/files/eB6zMUK6ZNSGhMqDEm2q" alt=""><figcaption><p>Protocol Epoch Schedule</p></figcaption></figure>


# Delegation Strategy

In the whole liquid staking system, the LiquidStaking.cdc contract serves as the Portal for Staking and Unstaking, and the DelegatorManager.cdc contract stores and manages all the underlying Delegators (shown in the figure below). In addition, there are some Delegation Strategy Bots and the responsibility of these bots is to choose which node to stake or unstake.&#x20;

<figure><img src="/files/u1eFqX72ScXiC55i4GbA" alt=""><figcaption><p>Liquid Staking System Structure</p></figcaption></figure>

### How are staking nodes selected?

Flow blockchain currently has a total of 400-450 nodes, and there are about 300-350 nodes that can be staked and delegated (excluding access nodes).

How to choose a node is a very complex problem. The following will list some current judgment features, and we will continue to optimize and update in the future.

* **Lifetime:** The length of time the node provides services is a very important feature. A node that has been successfully running for a long time is considered reliable, while a newly added node needs more time to be considered.
* **Historical slash records:** A node that has been penalized multiple times in history will be considered unstable, which will greatly affect its final score.
* **APY:** This is an indicator that determines user's reward. However, since all nodes on the Flow blockchain currently share the same apr, we will continue to pay attention to it and achieve higher profit potential for users by reaching user reward cut reductions with trusted node operators.
* **Node staking amount**: Although Flow has a limit on the minimum staking amount of each node, the risk can also be reduced by biasing high-share staking nodes (the amount staked by the delegators is not included here).
* **Delegator's staking amount:** We found that some nodes are too concentrated to stake a lot of user assets, which is very dangerous (eggs cannot be put in one basket). At the same time, in order to take into some decentralizations, we will try to disperse the user's delegations as much as possible.

<figure><img src="/files/8p7r3jnBAOycj2EmGyQo" alt=""><figcaption><p>User Counter on Node</p></figcaption></figure>

* **Trusted node list:** In addition to official nodes, we will cooperate with high-quality node operators to provide safer staking services and higher APY returns.

### How does will the strategy bot work?

The bot takes care of multiple operations, mainly collection & updating $stFlow price, nodes selection, staking selection and unstaking selection.

* The collection bot will start working immediately at the beginning of each new Flow Epoch. After successfully collecting all the delegate infos, the bot will push the protocol to start the next new Protocol Epoch. Anyone can run this bot.
* The selection bot will also evaluate all nodes at the beginning of a new Epoch. When staking occurs, it will give priority to the average staking under the high-quality nodes; and will give priority to unstake from the low-scoring nodes.


# FAQ

### What is Liquid Staking Protocol (LSP)?&#x20;

LSP allows users to earn staking rewards without locking `$flow` tokens or running node softwares. Users can deposit `$flow` tokens and receive transferrable `$stFlow` tokens in return. Liquid staking combines the benefits of staking (earning rewards) and brings liquidity, as well as additional possibilities to increase your assets or hedge your positions by participating in Flow’s DeFi ecosystem.

Furthermore, LSP stakes these tokens to a set of different node providers for the sake of decentralization, preventing any single point of failure, diversifying staking risks and stabilizing liquid staking apr.&#x20;

### What is `$stFlow` token and how can I get it?

`stFlow` is a fungible token on Flow blockchain that represents a share of the total `$flow` tokens staked through LSP, along with any generated staking rewards.

There is no waiting time for receiving `stFlow` tokens - you’ll receive the newly minted `stFlow` as soon as you delegate to LSP. You can also purchase `$stFlow` from the open market (e.g. DEX) directly.

Since the delegated `$flow` tokens accrue staking rewards, `$stFlow` is interest-bearing - meaning that its price grows on each flowchain's epoch advancement.

### How do I claim my staking rewards?&#x20;

The simple answer is: you don’t have to.

As explained above, `stFlow` represents both your staking amount and the rewards you earn on each epoch, so its price grows over time. The same amount of `$stFlow` entitles you to withdraw more Flow after each epoch.

### Can I unstake at any time?&#x20;

Yes. You have 2 options:

* Directly swap `$stFlow` back to `$flow` on the DEX, and you’ll get `$flow` tokens back immediately. Depending on the liquidity condition of `stFlow <> Flow` pair on DEX, sometimes it has better rates than normal unstaking.
* Perform an unstaking request by burning your `$stFlow` tokens for a redemption ticket, and you’ll find both your pending and matured unstaking requests in the `'Unstaking'` tab. Just like traditional unstaking, it takes 1\~2 epochs, and after it’s matured you can come back to withdraw.

### How long after (normal) unstaking can I withdraw my Flow?&#x20;

Depending on the time of your unstaking request, the waiting period is 1 \~ 2 epochs (1 epoch \~= 7 days). After that, you will be able to withdraw your claimable amount.

Source: <https://developers.flow.com/nodes/staking/schedule>

### What is Migrate? How to benefit from LSP if I’ve currently delegated to a node?&#x20;

**‘Migrate’** is a feature specifically built for existing delegators. So if you’ve delegated to a node already, you do not need to unstake from the node, but instead you can “migrate” the staked position to LSP and receive `$stFlow` immediately in 1 transaction.

If you don’t have any staked position, the card will be empty; otherwise the `Migrate` tab will be red dotted to give you a notice. Some notes here:

* Any unclaimed rewards or unstaked tokens will be migrated along with staked and newly commited tokens, **in 1 click**.
* Any *new unstake request* will be *canceled* and then the position will be migrated, all **in 1 click**.

There’re also certain ***restrictions*** on migratable staked positions though:

* If the staked position has any *ongoing unstaking request*, it is ***temporarily*** non-migratable: you’ll have to wait for 1 epoch until the unstaking request becomes ‘unstaked’ and then come back to the '`Migrate'` tab.
* If the staked position has used [locked account](https://developers.flow.com/flow/core-contracts/locked-tokens) to handle staking (for example: Blocto), you ***have to unstake from locked account*** first. Check `Unstake & Migrate`'s case in the [user guidance](https://docs.increment.fi/protocols/liquid-staking/user-guidance#4.-migrate) for more info.
* If you're staking through [Flow Port](https://port.onflow.org/), you should be good to go and migratable most of the case. (Unless you've staked any unvested tokens, see explanation in the end of [user guidance](https://docs.increment.fi/protocols/liquid-staking/user-guidance#4.-migrate))
* Encountered question with other staking providers and non-migratable? -> Let us know on [twitter](https://twitter.com/incrementfi) or [discord](http://discord.gg/r2keKxuKqX).

### Why should I use LSP other than traditional staking?

There are many reasons, just to name a few:

* **Instant liquidity**: You get instant liquidity (transferrable `$stFlow` token) while still earning staking rewards. Use `$stFlow` to participate in Flow’s DeFi ecosystem to earn more.&#x20;
* **Auto-compound**: There’s no need to manually claim staking rewards anymore. With LSP, the staking rewards are automatically claimed and restaked in the beginning of each new epoch (and thus auto-compounding!).
* **Option of instant unstaking**: As long as there’s enough liquidity on DEX, you can always choose to redeem `$stFlow` back to `$flow` immediately by swapping. Sometimes DEX has better rates than normal unstaking.
* **Composability for more yield opportunity**: With $stFlow, it unlocks broader yield opportunities. You can supply `$stFlow` on the lending market to earn double (or even triple) rewards. You can borrow more `$flow` to mint `$stFlow` with `$stFlow` as collaterals. You can earn trading fees (plus LP rewards) by providing liquidity to the `stFlow-Flow` pair, which has almost zero impermanent loss. And more opportunities waiting to be discovered.
* **Ease of use and risk diversification**:&#x20;
  * In traditional staking, users have to search by themselves and manually specify which node they’d like to delegate to. They also have to manually claim rewards, periodically check delegated node status and to perform unstake then stake if necessary.
  * As a comparison, with LSP one can start staking with a single click. Strategy bots will handle delegate distribution, auto-compound, slashed nodes detection, redelegation, according to different strategies (e.g. `nodeCut`, `uptime`, etc).
  * LSP benefits the decentralization of the whole network as well as some small node operators. LSP splits delegates among all eligible nodes other than delegating to a single, self-operated node.

### Has LSP been audited, and what are the risks involved?&#x20;

Yes, and you can find the audit report in [audits](/protocols/liquid-staking/security).

We put **security as top priority** in developing in the DeFi space, and besides security audits, we’ve also set up a [bug bounty](https://docs.increment.fi/miscs/bug-bounty) program for security researchers and white hats to help audit and protect LSP. The bounty program is also publicly accessible [here](https://bugrap.io/bounties/Increment%20Finance).&#x20;

### Which nodes are receiving delegates from LSP?

We do not spin up our own nodes, so the delegated tokens are not staked to us.

We adopt the practice to stay transparent and reach progressive decentralization over time. The end goal is to let token holders (in future we’ll release the token) vote and distribute delegates in a weighted manner. However, right now there’s an allowlist of nodes, only nodes within the allowlist are eligible to receive delegates from LSP.&#x20;

Nodes in the list are chosen based on reputation, former experiences in maintaining node infrastructure, partnership, and so on. Current nodelist included nodes running by below entities:

<table><thead><tr><th width="508">NodeID</th><th width="92">Weight</th><th>Node Runner</th></tr></thead><tbody><tr><td><code>3c6519ba8be35e338df7273a895ad3abaeb0c232eb908ee7b05462018c112fe1</code></td><td><code>1.0</code></td><td><code>Flow Wallet</code> </td></tr><tr><td><code>093132ae6b090b3cf3b14d5da282e8a9cc6e5158342a83354c4fd27d5263416e</code></td><td><code>1.0</code></td><td><code>Versus</code></td></tr><tr><td><code>8f8d77ba98d1606b19fce8f6d35908bfc29ea171c02879162f6755c05e0ca1ee</code></td><td><code>1.0</code></td><td><code>Blockchain at Berkeley</code></td></tr><tr><td><del><code>581525fa93d8fe4b334c179698c6e72baccb802593e55e40da61d24e589d85be</code></del></td><td><del><code>1.0</code></del></td><td><del><code>Flipside</code></del></td></tr><tr><td><del><code>55069e7e8926867bee8094bd31786f8f6b65c8c3bde468ae2275f33dc1245dc1</code></del></td><td><del><code>1.0</code></del></td><td><del><code>HashQuark</code></del></td></tr></tbody></table>

\*A list of well-known nodes can be found [**here**](https://github.com/onflow/flow/blob/master/nodeoperators/NodeOperatorList.md). If you’re a node operator and would like to join the node program, please fill in this [**form**](https://forms.gle/qecncA6j5N3PTiQ47) and tell us on discord / twitter / email.

### What is the current Delegation Strategy?

There are 4 types of nodes that are eligible to receive staking rewards: `Execution`, `Consensus`, `Collection`, and `Verification`. Right now all of them are applied with the same rewards weight, but it may change in the future according to Flow’s plan. Also currently nodes cannot customize the `nodeCut` parameter, as it’s fixed to `8%`, however, this is also updatable in future.

So for now, the delegation strategy is simple enough: it will try to evenly distribute delegates to eligible nodes. But in the future once the node weight and node cut feature have been upgraded, the delegation strategy would also be upgraded accordingly, including but not limited to metrics like self-bonded amount, uptime, slashing history, etc.

### What fees does LSP charge?&#x20;

The fee parameter is configurable, and right now there is a 10% fee applied on users’ staking rewards (it’s only applied on generated staking rewards, not on staked principal). The fee is used to continuously fund operations, marketing expenses, `stFlow <> Flow` LP rewards, insurance funds, auditing expenses, and future development, etc., to boost adoption and build a network effect of `$stFlow`.

### More questions?

Find us on [Twitter](https://twitter.com/incrementfi) or [Discord](http://discord.gg/r2keKxuKqX) and let us know.


# Node Registration

As mentioned in the [FAQ](/protocols/liquid-staking/faq#which-nodes-are-receiving-delegates-from-lsp), we do not run our own nodes, so the delegated tokens are not staked to us.

We adopt the practice to stay transparent and reach progressive decentralization over time. The end goal is to let token holders (in future we’ll release the token) vote and distribute delegates in a weighted manner. However, ***right now*** there’s an allowlist of nodes, only nodes within the allowlist are eligible to receive delegates from LSP.&#x20;

A list of well-known nodes can be found [**here**](https://github.com/onflow/flow/blob/master/nodeoperators/NodeOperatorList.md). If you’re a node operator and would like to join the node program, please fill in this [**form**](https://forms.gle/qecncA6j5N3PTiQ47) and tell us on discord / twitter / email.


# Security

**📔 Audited by Oak Security: =>** [**Link**](https://increment-audit.s3.us-west-1.amazonaws.com/Audit+Report+-+IncrementFi+Liquid+Staking.pdf)

#### **🐛Bug bounty:** <https://docs.increment.fi/miscs/bug-bounty>


# Points

{% hint style="info" %}
The launch of the points program is to:

1\) Gamify user experiences on Increment;

2\) Quantify and reward user contributions;

Points can be earned in multiple ways as described in this section. Point earning rule is subject to change as new products launch or during temporary promotional periods.

The Points Program also features a Leaderboard, where community members are able to track their own ranking along with top contributing users and top influencers by referrals.
{% endhint %}

<https://app.increment.fi/points>


# Rules

Last Revision: March 24, 2024 (Changes made: 2X points earning of stFlow/Flow stableswap pair and 10X points earning of swaps to $stFlow)

## ✨ How to Earn Points

<figure><img src="/files/b1VmhGmuxmvE9FscMxJk" alt=""><figcaption></figcaption></figure>

You can earn points by holding stFlow, swapping, lending / borrowing, providing liquidity, and referring new users. Points are categorized into two main types:

* **Activity Points**: Earn through DeFi activities on Increment.
* **Referral Points**: Earn 5% of the activity points of the users you refer (without lowering their own activity points).&#x20;

## **💪** Activity Points: Use-to-Earn

Here are 5 key DeFi activities to earn points on Increment. You can customize your own strategy to maximize your points while interacting with Increment:

* **Hold stFlow**: It will earn you **24** points per day for every 1,000 $stFlow tokens holding in the wallet. The longer you hold and the more $stFlow you have, the more points you will get.
* **Lend**: It will earn you **2.4** points per day for every $1,000 worth of funds deposited into the lending pool. The more and the longer you deposit in the lending pool, the more points you will earn.
* **Borrow**: It will earn you **12** points per day for every $1,000 worth of funds borrowed from the lending pool. The more and the longer you borrow, the more points you will earn.
* **Provide Liquidity & Stake into Farms**: It will earn you **30** points per day for every $1,000 worth of liquidity provided to certain swap pairs. The LP tokens have to be **staked into active Farms** to earn the points. <mark style="color:blue;">(\*Note that starting from March 24 2024, LP of stFlow/Flow stableswap pool earns</mark> <mark style="color:blue;"></mark><mark style="color:blue;">**2X**</mark> <mark style="color:blue;"></mark><mark style="color:blue;">- 60 points / day / 1K worth of lpToken)</mark>
* **Swap**: It will earn you **1.0** point for every $1,000 worth of swap trade through Increment. The more trading volumes you make, the more points you will earn. <mark style="color:blue;">(\*Note that starting from March 24 2024, trades that swapped to $stFlow earns</mark> <mark style="color:blue;"></mark><mark style="color:blue;">**10X**</mark> <mark style="color:blue;"></mark><mark style="color:blue;">- 10 points / $1K worth of swap)</mark>

*(\* Noting that the above data is pro-rata based with 1.0 as minimum qualifying threshold. For example Alice will earn 0.01 point per hour if holding 10 $stFlow, but she will earn nothing if holding less than 1.0 $stFlow.)*

**Example 1**: User Alice

* Holds 2,000 $stFlow
* Lends 2,000 $Flow
* Borrows 1,000 $USDC
* Provides {500 $Flow + 446 $stFlow} liquidity to Flow<>stFlow stableswap-pool => receives 900 lpTokens => Just staked 500 lpToken into the corresponding active Farm
* Swapped 1,000 $Flow to $USDC, 500 $Flow to $stFlow

Assuming 1 $Flow = $1.1, 1 $stFlow = 1.12 $Flow, Alice will:

1. **Earn points from holding stFlow**: 24 points / 1,000 stFlow / day:&#x20;
   * 24 / 1000 \* 2000 = 48 points / day
2. **Earn points from Lending**: 2.4 points / $1,000 / day
   * 2.4 / 1000 \* 2000 \* 1.1 = 5.28 points / day
3. **Earn points from Borrowing**: 12 points / $1,000 / day
   * 12 / 1000 \* 1000 = 12 points / day
4. **Earn points from Staked LP**: 30 points / $1,000 Staked LP / day (<mark style="color:blue;">**2X weight**</mark>, i.e. 60 for stFlow/Flow stableswap pair)
   * 60 / 1000 \* ((500 \* 1.1 + 446 \* 1.12 \* 1.1) \* 500 / 900) = 36.65 points / day
5. **Earn points from Swapping**: 1 point / $1,000 swap size (<mark style="color:blue;">**10X weight**</mark> for swapping to $stFlow, i.e. 10 points / $1K swap size)
   * 1 / 1000 \* 1000 \* 1.1 + 10 / 1000 \* 500 \* 1.1 = 6.6 points

**Total** = 48 + 5.28 + 12 + 36.65 + 6.6 = **108.53 Points / day**

\
\* Noting that only lpTokens staked into active Farms will be counted. The current active Farms are:&#x20;

* Flow<>USDC LP-Farm
* Flow<>stFlow (Stableswap-pair) LP-Farm (2X weight, i.e. 60 points  / $1K staked LP / day)
* Flow<>DUST LP-Farm
* Flow<>Loppy LP-Farm

The farms are setup on a monthly basis and may change based on adoption, partnership, and performance of the program. Please join our [discord](https://discord.gg/r2keKxuKqX) community to get alerts of these changes.

## **👥** Referral Points: Earn 5% extra from Referrals

<figure><img src="/files/U9vmI3wmFuflmUssut9C" alt="" width="563"><figcaption></figcaption></figure>

This is a **mutual beneficial** opportunity for both you and the people you refer:

1. Share your referral link with your friends.
2. When your friends use your referral code and keep using Increment, everyone wins.
3. You'll receive 5% of their activity points, and your referees will also enjoy a 5% earning rate speed-up of their activity points.

Keep in mind that this benefit has an ongoing effect: as long as your referees keep earning activity points, you'll continuously receive 5% of their newly earned activity points.

Please note that the 5% referral points bonus only takes effect after your invitation is accepted (they bind your referral code), and thus cannot be applied retroactively.

## 🚀 Boost Earning Rate

<figure><img src="/files/eusbHIKtbN0N8KjB3d3Q" alt="" width="375"><figcaption></figcaption></figure>

### **👐** Holding a Core Member NFT:

By holding the Increment Core Member NFT, you will get a **20%** earning rate boost of your activity points.

**Example 2:** Take the example from 1.&#x20;

After Alice obtains the Increment Core Member NFT, her point earning rate will be increased by 20%, so from now on, she will get: 108.53 \* (1+20%) = **130.236 Points / day**

### **🔗** Binding a Referral Code:

By binding a referral code, you will get another **5%** earning rate boost of your activity points.

When sharing out your referral link, do not forget to tell your potential referees this benefit.

It is highly recommended that all users bind a referral code to get this 5% boost.

**Example 3**: Take the same example from 2.&#x20;

After Alice binds a referral code, her point earning rate will get another 5% increase.&#x20;

Now her total boost becomes 25% (calculated linearly). So from now on, she will get: 108.53 \* (1+25%) = **135.663 Points / day**

There will also be future boosts that may last for a limited time to promote a partnership, attract liquidity for certain assets, etc.

Please stay tuned and turn on post notifications in X to get first time alerts of these promotions.

## 🎉 OG Points (Retroactive Points Airdrop)

<figure><img src="/files/2rpm7TwzsnyFBEK9QBOv" alt="" width="257"><figcaption></figcaption></figure>

The OG Points Program is to reward our OG users who have been with us since the early days and grow with us all the way on Flow.&#x20;

The snapshot was taken on March 4 2024 11:00 (GMT+0) for previous qualified activities on Increment. Qualified users will notice a flashing giftbox 🎁 on the top left corner of the page as a notification to claim their OG Points airdrop.

Please note that OG points must be claimed **within 2 months** from the launch time (March 4, 2024) of the Points Program. Non-claimed OG points will be burnt after the claiming window.

## 🏆 Points Ranking & Leaderboard Update

<figure><img src="/files/VAT8LMijfa1wVjO5aY7J" alt="" width="375"><figcaption></figcaption></figure>

The leaderboard ranks top-30 participants in the Points Program by total points and referral points respectively. There may be extra rewards for the top participants such as distributing the Core Member NFT, guaranteed whitelist, et al. Please stay tuned and turn on post notifications in X to get first time alerts.

Most of the activities accumulate points **in real-time** (and thus Leaderboard is updated near real-time), but for points earned from swapping and points earned from referrals there's a delay. The leaderboard will be **updated once a week** on Sunday, to accurately include the points earned from all activities in the past week.

## ❓ Questions

If you have any questions on the point program, please ask the team in Discord and we can assist you with the right direction.


# Terms

Last Updated: March 5, 2025

PLEASE READ THESE TERMS AND CONDITIONS CAREFULLY.&#x20;

BY ACCESSING OR PARTICIPATING IN THE INCREMENT POINTS PROGRAM, YOU AGREE TO BE BOUND BY THESE TERMS AND CONDITIONS AND ALL TERMS INCORPORATED BY REFERENCE. IF YOU DO NOT AGREE TO THESE TERMS, DO NOT PARTICIPATE IN THE INCREMENT POINTS PROGRAM.&#x20;

### 1. Introduction

The Increment Points Program(“Points Program”) is operated by Increment Labs ("Increment Labs," "we," "us," or "our"). The Points Program is applicable to all users (“you”, “your” or "Participant") of the Increment applications (“Increment App”).

It is designed to reward users for engaging with our platform and services. Participation in the Program allows you to earn points ("Points"), as described in these Terms and Conditions ("Points Terms").&#x20;

### 2. General Application of Terms; Privacy

Terms apply to any access to and/or participation in the Points Program existing now or in the future. These Terms are in addition to: (1) the then-current Terms of Service, available at[ ](https://jito-labs.gitbook.io/mev/references/terms-of-service)<https://docs.increment.fi/miscs/term-of-service>, and (2) the then-current Privacy Policy, available at[ ](https://jito-labs.gitbook.io/mev/references/privacy-policy)<https://docs.increment.fi/miscs/privacy-policy> (collectively, the “Increment Terms”), but in each case only to the extent necessary to govern your participation in the Points Program. All capitalized terms used but not defined herein shall have the respective meanings given to them in the Increment Terms. If these Points Terms are inconsistent with any part of the Increment Terms, these Points Terms will govern your participation in the Points Program.

Please read the Increment Terms carefully to understand how Increment Labs collects, uses and discloses information about its customers. These Points Terms do not alter in any way the terms or conditions of any other agreement you may have with Increment Labs for other products and services, or the terms or conditions of any other promotional offers or programs conducted by Increment Labs outside the context of the Points Program.

### 3. Eligibility

The Program is open to all users of Increment Apps who are in compliance with our Terms of Service and Privacy Policy.

Participants must be of legal age in their jurisdiction of residence.

The Points are intended for personal use only. Commercial use is prohibited.

### 4. Earning Points

The Points Program is a mechanism that allows you to accumulate points (“Points”) based on your usage and interaction with the App and services provided therein. The number of Points earned may vary depending on the nature of your interaction with the App.

We reserve the right to determine, in our sole discretion, the number of Points awarded for any given interaction.

### 5. ​Changes to the Points Program

We expressly reserve the right, in our sole and absolute discretion, to modify, alter, or change the calculation or valuation of Points at any time and for any reason without prior notice.

Such modifications, alterations, or changes may include, but are not limited to, increasing or decreasing the number of Points awarded for a specific interaction, changing the activities for which Points may be awarded, or imposing limits on the accumulation or redemption of Points.

### 6. No Monetary Value

Points have no cash value, are not exchangeable for cash, and are not transferable. The sale, barter, or other disposal of Points, other than by us, is expressly prohibited.

### 7. Limitations and Restrictions

Increment Labs’ determinations of participant eligibility or any questions or disputes arising under the Points Program, these Points Terms, or any other Increment Labs rules or restrictions shall be final and binding and not subject to challenge or appeal.

Without notice to you, Increment Labs reserves the right to suspend or terminate the Points Program or your participation in the Points Program if Increment Labs determines in its sole discretion that you have violated these Points Terms, or that the use of your Points is unauthorized, deceptive, fraudulent, unlawful, or intentionally subverts the purposes of these Points Terms.

There are no membership fees associated with the Points Program, although use of online services in conjunction with participation in the Points Program may result in data charges, internet access fees, or similar expenses.

Points accumulated under the Increment Labs Points Program have no cash value. Accumulated Points must be redeemed within 24 months from the date of accrual, after which they will expire. OG points must be claimed within two(2) months from the date of the Points Program launches.

Increment Labs is not responsible for any problems or technical malfunction of any telephone, Internet or blockchain network or lines, online systems, servers, providers, computer equipment, software, or messaging platform, or as a result of technical problems or traffic congestion on the Internet, any website, or any application, or any combination thereof, including, without limitation, any resulting error in computing qualifying actions or any unavailability of Points, or any injury or damage to any participant’s or any other person’s computer or mobile device related to or resulting from participation in the Points Program. If, for any reason, the Points Program is not capable of running as planned, including due to errors of any kind or nature, infection by computer viruses, bugs, tampering, unauthorized intervention, fraud, technical failures, or any other causes beyond the control of Increment Labs which corrupt or affect the administration, security, fairness, integrity, or proper conduct of the Points Program, Increment Labs reserves the right in its sole discretion to cancel, terminate, modify, or suspend the Points Program or otherwise respond to the circumstances as Increment Labs deems appropriate.

### 8. Disclaimers

THE VALUE OF CRYPTOCURRENCY AND DIGITAL ASSETS ARE SUBJECT TO CHANGE. THERE CAN BE A SUBSTANTIAL RISK THAT IT COULD LOSE VALUE (POSSIBLY ALL VALUE) AS A RESULT OF RECEIVING, BUYING, SELLING, OR HOLDING CRYPTOCURRENCY AND OTHER DIGITAL ASSETS.

The value of any digital asset is subjective and therefore can be volatile. Digital and similar assets have no inherent or intrinsic value. Increment Labs does not and cannot guarantee that any digital asset you hold will retain its original value. You agree to assume all risk associated with the use and value of the digital asset.

THE POINTS PROGRAM IS PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND. WITHOUT LIMITING THE FOREGOING, WE EXPLICITLY DISCLAIM ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT, AND NON-INFRINGEMENT, AND ANY WARRANTIES ARISING OUT OF COURSE OF DEALING OR USAGE OF TRADE. We make no warranty that the Points Program will meet your requirements or be available on an uninterrupted, secure, or error-free basis. We make no warranty regarding the quality, accuracy, timeliness, truthfulness, completeness, or reliability of any information or content provided through the Points Program. WE WILL NOT BE LIABLE FOR ANY LOSS OF ANY KIND FROM ANY ACTION TAKEN OR TAKEN IN RELIANCE ON MATERIAL OR INFORMATION CONTAINED IN THE POINTS PROGRAM. INCREMENT LABS WILL NOT BE RESPONSIBLE FOR OR LIABLE TO YOU FOR ANY LOSS FOR ANY USE OF THE SERVICES. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES. ACCORDINGLY, SOME OF THESE DISCLAIMERS OF WARRANTIES MAY NOT APPLY TO YOU.

### 9. Indemnification

You agree to release, indemnify, defend, and hold harmless Increment Labs and its parent, affiliates, subsidiaries, directors, officers, employees, sponsors, agents, and assigns, including advertising and promotion agencies and any other organizations related to the Points Program, from any and all claims, injuries, damages, expenses, or losses to person or property and/or liabilities of any nature that in any way arise from participation in the Points Program or acceptance or use of any Points, including, without limitation, (i) any condition caused by events beyond Increment Labs’ control that may cause the Points Program to be disrupted or corrupted; and (ii) any printing or typographical errors in any materials associated with the Points Program.

### 10. Governing Law

Increment Labs may restrict services, including in certain jurisdictions due to applicable laws, regulations or business considerations at its sole discretion. Increment Labs will not be liable for any loss or damage resulting from the temporary or permanent loss of use to any service or related services.

These Terms are governed by the laws of the jurisdiction in which Increment Labs is incorporated, without regard to its conflict of law principles.

### 11. Contact Information

If you have any questions relating to the Points Program, you may contact us via email at <contact@increment.fi>.<br>


# Metrics

### Defillama 🦙:

* <https://defillama.com/protocol/increment-finance>

### Coingecko 🐸:

* <https://www.coingecko.com/en/exchanges/increment-swap>
* <https://www.coingecko.com/en/coins/liquid-staked-flow>

### DappRadar 🛰️:&#x20;

* <https://dappradar.com/flow/defi/increment-finance>

### Stats 📊:&#x20;

* <https://app.increment.fi/infos>&#x20;


# Tutorials

### Medium articles

* **Swap** - <https://incrementfi.medium.com/a-user-guidance-to-decentralized-exchange-110cb8b2202>
* **Farm** - <https://medium.com/coinmonks/introducing-lp-farms-22861d5b0e92>
* **Lending & Borrowing** - <https://medium.com/coinmonks/introducing-increment-earn-556420d770af>
* **Liquid Staking** - <https://medium.com/coinmonks/introducing-increment-liquid-staking-2cc04e7eae9d>
* **DEX Aggregator** - <https://medium.com/coinmonks/introducing-the-dex-aggregation-and-smart-order-routing-9c467e4c3673>&#x20;

### Video tutorials by Flowverse

* **Swap** - <https://twitter.com/flowverse_/status/1533696877983846400>&#x20;
* **Lending** - <https://twitter.com/flowverse_/status/1541268110267023366>&#x20;
* **Liquid Staking** - <https://twitter.com/flowverse_/status/1587968924540612608>

### **Strategies & tutorials by big brain** 🧠 **community members**

* <https://twitter.com/ElDumboTS/status/1727410442849624463>


# Security Audits

### Oak Security

* Swap: Internally audited by the Cadence team (deployed before Flow permissionless deployment)
* Lending & Borrowing, Oracle: <https://increment-audit.s3.us-west-1.amazonaws.com/Audit+Report+-+Increment+Finance.pdf>&#x20;
* Liquid Staking: <https://increment-audit.s3.us-west-1.amazonaws.com/Audit+Report+-+IncrementFi+Liquid+Staking.pdf>


# Bug Bounty

A bug bounty program for Increment's smart contracts is now live. Whitehats are welcome to submit reports either on [https://bugrap.io/ ](https://bugrap.io/)or through emails.

## Rewards

Vulnerability reports will be scored using the [CVSS v3](https://www.first.org/cvss/) standard. The reward amounts for different types of vulnerabilities are:

**🚨 Critical (CVSS 9.0–10.0)**

→ $5,000 - $15,000

**⚠️ Major (CVSS 7.0–8.9)**

→ $2,500 - $5,000​&#x20;

**⚡ Medium (CVSS 4.0–6.9)**

→ $750 - $2,500

**🐛 Low (CVSS 1.0–3.9)**

→ $500 - $750

Rewards will be awarded at the sole discretion of Increment Team. Quality of the report and reproduction instructions can impact the reward. Rewards are denominated and paid out in USD. If both parties agree, rewards can also be paid out in crypto.

The bug bounty program is ongoing and has been running since July 20 2022.

## Reporting a Vulnerability

Please responsibly disclose any findings to the development team, following these instructions:

* In order to report a vulnerability, please write an email to **<contact@increment.fi>** with \[SECURITY DISCLOSURE] in the subject of the email.
* We will make our best effort to reply in a timely manner and provide a timeline for resolution.
* Please include a detailed report on the vulnerability with *clear* reproduction steps. The quality of the report can impact the reward amount.

Failure to do so will result in a finding being ineligible for any bounties.

## Scope

In scope for the bug bounty are all the smart contract components of the Increment protocols. They can be found in the following sections:

* [AMM DEX Smart Contracts](https://docs.increment.fi/protocols/decentralized-exchange/cpamm-dex/deployment-addresses)
* [Stableswap AMM Smart Contracts](https://docs.increment.fi/protocols/decentralized-exchange/stableswap-dex/deployment-addresses)
* [Decentralized Money Market Smart Contracts](https://docs.increment.fi/protocols/decentralized-money-market/deployment-addresses)
* [Decentralized Price Feed Smart Contracts](https://docs.increment.fi/protocols/decentralized-price-feed/deployment-addresses)
* [Liquidity Mining Smart Contracts](https://docs.increment.fi/protocols/liquidity-mining-farm/token-farm/deployment-addresses)
* [Liquid Staking Smart Contracts](https://docs.increment.fi/protocols/liquid-staking/deployment-addresses)

## Out of scope

* Any frontend applications or client-side code interacting with the contracts, as well as testing code.&#x20;
* Mismatch of the functionality of the contracts and outdated spec documents.

## Areas of interest

These are some examples of vulnerabilities that would be interesting:&#x20;

* Stealing tokens or manipulating the token generation process.
* Locking or freezing any of the Increment's contracts.
* Griefing attacks: is it possible to block liquidations, redemptions, borrower operations, etc?
* Do the desired constraints on borrower operations hold?
* Flash loan exploits

## Resources

* [Increment Documentations](https://docs.increment.fi/)

## Eligibility

Terms for eligible bounties:&#x20;

* Only unknown vulnerabilities will be awarded a bounty; in case of duplicate reports, the first report will be awarded the bounty.
* Public disclosure of the vulnerability, before explicit consent from Increment Team to do so, will make the vulnerability ineligible for a bounty.
* Attempting to exploit the vulnerability in Flow mainnet will also make it ineligible for a bounty.&#x20;


# Brand Assets

### Increment Logo

* No text
  * [Transparent](https://drive.google.com/file/d/1kYAHJpUWChwQtBgB8KK97SnyBSNlgJsj/view?usp=sharing)
  * [White](https://drive.google.com/file/d/1oLSvZewwbIUlizhWllkrkXQuocU8WN-h/view?usp=sharing)
* With text
  * [Landscape transparent](https://drive.google.com/file/d/1ATNdDs14yBunKUZtl0-OZngxDFU9pscK/view?usp=sharing)
  * [Landscape white](https://drive.google.com/file/d/1FN3ssGKvrVUQcF9KNlKGm2U5HvCWs9Hh/view?usp=sharing)
  * [Portrait transparent](https://drive.google.com/file/d/1UH2B5DHddXZSnohwce-5PNsCQzbDycHC/view?usp=sharing)
  * [Portrait white](https://drive.google.com/file/d/1iVDYp3n77m-qFAMktOwR16iw80IcleYW/view?usp=sharing)

### stFlow logo

* [PNG file](https://drive.google.com/file/d/1P8oPYlnq4kdbn_aJntqwQnxazLnDX-KI/view?usp=sharing)
* [SVG file](https://drive.google.com/file/d/1sVYmGPzEk1iYX9Q9A758qG3KV-_786KA/view?usp=sharing)


# Decentralized Web

The application's frontend is also hosted on IPFS, Internet Computer (ICP), and Arweave.

* **ICP:**
  * Url-1: <https://6gscy-faaaa-aaaag-abgga-cai.ic0.app>
* **IPFS:**&#x20;
  * Content-Hash: `bafybeigfs624u4dq3ouqbughnradgrbs4eioadlxneoqjd5okk5eyawefi`
  * Url-1: [https://increment-web-ipfs.4everland.app](https://increment-web-ipfs.4everland.app/)
  * Url-2: [https://bafybeigfs624u4dq3ouqbughnradgrbs4eioadlxneoqjd5okk5eyawefi.ipfs.dweb.link](https://bafybeigfs624u4dq3ouqbughnradgrbs4eioadlxneoqjd5okk5eyawefi.ipfs.dweb.link/)
* **Arweave:**&#x20;
  * Url-1: [https://increment-web-arweave.4everland.app](https://increment-web-arweave.4everland.app/)
  * Ar-tx: <https://viewblock.io/arweave/tx/u75x-dcMsDe9wpecli5-2oM7NNzLiY6rzg0Oa6kk0sw>


# Term of Service

Last modified: July 10, 2025

These Terms of Service (the "Agreement") explain the terms and conditions by which you may access and use the Products provided by Increment Labs (referred to herein as "Increment Labs", "we", "our", or "us").  The Products shall include, but shall not necessarily be limited to, (a)  <https://app.increment.fi>, a website-hosted user interface (the "Interface" or "App"), (b) The set of smart contracts written in Cadence and deployed on the Flow blockchain. You must read this Agreement carefully as it governs your use of the Products. By accessing or using any of the Products, you signify that you have read, understand, and agree to be bound by this Agreement in its entirety. If you do not agree, you are not authorized to access or use any of our Products and should not use our Products.

To access or use any of our Products, you must be able to form a legally binding contract with us. Accordingly, you represent that you are at least the age of majority in your jurisdiction (e.g., 18 years old in the United States) and have the full right, power, and authority to enter into and comply with the terms and conditions of this Agreement on behalf of yourself and any company or legal entity for which you may access or use the Interface.  If you are entering into this Agreement on behalf of an entity, you represent to us that you have the legal authority to bind such entity.&#x20;

You further represent that you are not the subject of economic or trade sanctions administered or enforced by any governmental authority or otherwise designated on any list of prohibited or restricted parties (including but not limited to the list maintained by the Office of Foreign Assets Control of the U.S. Department of the Treasury). Finally, you represent that your access and use of any of our Products will fully comply with all applicable laws and regulations, and that you will not access or use any of our Products to conduct, promote, or otherwise facilitate any illegal activity.

NOTICE: This Agreement contains important information, including a binding arbitration provision and a class action waiver, both of which impact your rights as to how disputes are resolved. Our Products are only available to you — and you should only access any of our Products — if you agree completely with these terms.&#x20;

## 1. Our Products

### 1.1 The Interface

The Interface provides a web or mobile-based means of access to (a) a decentralized protocol on public blockchains, including but not limited to Flow, that allows users to trade certain compatible digital assets (the "Swap Protocol"); and (b) a decentralized protocol on public blockchains, including but not limited to Flow, that allows users to supply and borrow certain compatible digital assets (the “Lending Protocol”); and (c) a decentralized protocol on public blockchains, including but not limited to Flow, that allows users to and stake certain compatible digital assets (the “Liquid Staking Protocol”).&#x20;

The Interface is distinct from the Protocol and is one, but not the exclusive, means of accessing the Protocol. The Protocol comprises open-source or source-available self-executing smart contracts that are deployed on various public blockchains, such as Flow. Increment Labs does not control or operate any version of the Protocol on any blockchain network. By using the Interface, you understand that you are not buying or selling digital assets from us and that we do not operate any liquidity pools on the Protocol or control trade execution on the Protocol. When traders pay fees for trades, those fees accrue to liquidity providers for the Protocol. As a general matter, Increment Labs is not a liquidity provider into Protocol liquidity pools and liquidity providers are independent third parties.&#x20;

To access the Interface, you must use a wallet software, which allows you to interact with public blockchains. Your relationship with that wallet provider is governed by the applicable terms of service of those third parties.  We do not have custody or control over the contents of your wallet and have no ability to retrieve or transfer its contents. By connecting your wallet to our Interface, you agree to be bound by this Agreement and all of the terms incorporated herein by reference.

### 1.2 Other Products

We may from time to time in the future offer additional products, and such additional products shall be considered a Product as used herein, regardless of whether such product is specifically defined in this Agreement.&#x20;

### 1.3 Third Party Services and Content

When you use any of our Products, you may also be using the products, services or content of one or more third parties.  Your use of such third party products, services or content may be subject to separate policies, terms of use and fees of these third parties, and you agree to abide by and be responsible for such policies, terms of use and fees, as applicable.&#x20;

## 2. Modifications of this Agreement or our Products

### 2.1 Modifications of this Agreement

We reserve the right, in our sole discretion, to modify this Agreement from time to time. If we make any material modifications, we will notify you by updating the date at the top of the Agreement and by maintaining a current version of the Agreement at [https://docs.increment.fi/miscs/term-of-service](/miscs/term-of-service). All modifications will be effective when they are posted, and your continued accessing or use of any of the Products will serve as confirmation of your acceptance of those modifications. If you do not agree with any modifications to this Agreement, you must immediately stop accessing and using all of our Products.

### 2.2 Modifications of our Products

We reserve the following rights, which do not constitute obligations of ours: (a) with or without notice to you, to modify, substitute, eliminate or add to any of the Products; (b) to review, modify, filter, disable, delete and remove any and all content and information from any of the Products. &#x20;

## 3. Intellectual Property Rights

### 3.1 IP Rights Generally

We own all intellectual property and other rights in each of our Products and its respective contents, including, but not limited to, software, text, images, trademarks, service marks, copyrights, patents, designs, and its "look and feel." This intellectual property is available under the terms of our copyright licenses and our trademark guidelines.  Subject to the terms of this Agreement, we grant you a limited, revocable, non-exclusive, non-sublicensable, non-transferable license to access and use our Products  solely in accordance with this Agreement.  You agree that you will not use, modify, distribute, tamper with, reverse engineer, disassemble or decompile any of our Products for any purpose other than as expressly permitted pursuant to this Agreement.  Except as set forth in this Agreement, we grant you no rights to any of our Products, including any intellectual property rights.

You understand and acknowledge that the Protocol is not a Product and we do not control the Protocol.

By using any of our Products (including to list, post, promote, or display NFTs), you grant us a worldwide, non-exclusive, sublicensable, royalty-free license to use, copy, modify, and display any content, including but not limited to text, materials, images, files, communications, comments, feedback, suggestions, ideas, concepts, questions, data, or otherwise, that you post on or through any of our Products for our current and future business purposes, including to provide, promote, and improve the services. This includes any digital file, art, or other material linked to or associated with any NFTs that are displayed.  You grant to us a non-exclusive, transferable, worldwide, perpetual, irrevocable, fully-paid, royalty-free license, with the right to sublicense, under any and all intellectual property rights that you own or control to use, copy, modify, create derivative works based upon  any suggestions or feedback for any purpose.

You represent and warrant that you have, or have obtained, all rights, licenses, consents, permissions, power and/or authority necessary to grant the rights granted herein for any material that you list, post, promote, or display on or through any of our Products (including, but not limited to, NFTs). You represent and warrant that such content does not contain material subject to copyright, trademark, publicity rights, or other intellectual property rights, unless you have necessary permission or are otherwise legally entitled to post the material and to grant us the license described above, and that the content does not violate any laws.

### 3.2 Third-Party Resources and Promotions

Our Products may contain references or links to third-party resources, including, but not limited to, information, materials, products, or services, that we do not own or control. In addition, third parties may offer promotions related to your access and use of our Products. We do not approve, monitor, endorse, warrant or assume any responsibility for any such resources or promotions. If you access any such resources or participate in any such promotions, you do so at your own risk, and you understand that this Agreement does not apply to your dealings or relationships with any third parties. You expressly relieve us of any and all liability arising from your use of any such resources or participation in any such promotions.

### 3.3 Additional Rights

&#x20;We reserve the right to cooperate with any law enforcement, court or government investigation or order or third party requesting or directing that we disclose information or content or information that you provide.

## 4. Your Responsibilities&#x20;

### 4.1 Prohibited Activity

You agree not to engage in, or attempt to engage in, any of the following categories of prohibited activity in relation to your access and use of the Interface:

* Intellectual Property Infringement. Activity that infringes on or violates any copyright, trademark, service mark, patent, right of publicity, right of privacy, or other proprietary or intellectual property rights under the law.
* Cyberattack. Activity that seeks to interfere with or compromise the integrity, security, or proper functioning of any computer, server, network, personal device, or other information technology system, including, but not limited to, the deployment of viruses and denial of service attacks.
* Fraud and Misrepresentation. Activity that seeks to defraud us or any other person or entity, including, but not limited to, providing any false, inaccurate, or misleading information in order to unlawfully obtain the property of another.
* Market Manipulation. Activity that violates any applicable law, rule, or regulation concerning the integrity of trading markets, including, but not limited to, the manipulative tactics commonly known as "rug pulls", pumping and dumping, and wash trading.
* Securities and Derivatives Violations. Activity that violates any applicable law, rule, or regulation concerning the trading of securities or derivatives, including, but not limited to, the unregistered offering of securities and the offering of leveraged and margined commodity products to retail customers in the United States.
* Sale of Stolen Property. Buying, selling, or transferring of stolen items, fraudulently obtained items, items taken without authorization, and/or any other illegally obtained items.
* Data Mining or Scraping. Activity that involves data mining, robots, scraping, or similar data gathering or extraction methods of content or information from any of our Products.
* Objectionable Content. Activity that involves soliciting information from anyone under the age of 18 or that is otherwise harmful, threatening, abusive, harassing, tortious, excessively violent, defamatory, vulgar, obscene, pornographic, libelous, invasive of another's privacy, hateful, discriminatory, or otherwise objectionable.
* Any Other Unlawful Conduct. Activity that violates any applicable law, rule, or regulation of the United States or another relevant jurisdiction, including, but not limited to, the restrictions and regulatory requirements imposed by U.S. law.

### 4.2 Trading

You agree and understand that: (a) all trades you submit through any of our Products are considered unsolicited, which means that they are solely initiated by you; (b) you have not received any investment advice from us in connection with any trades, including those you place via our Auto Routing API; and (c) we do not conduct a suitability review of any trades you submit.

### 4.3 Non-Custodial and No Fiduciary Duties

Each of the Products is a purely non-custodial application, meaning we do not ever have custody, possession, or control of your digital assets at any time. It further means you are solely responsible for the custody of the cryptographic private keys to the digital asset wallets you hold and you should never share your wallet credentials or seed phrase with anyone. We accept no responsibility for, or liability to you, in connection with your use of a wallet  and make no representations or warranties regarding how any of our Products will operate with any specific wallet. Likewise, you are solely responsible for any associated wallet and we are not liable for any acts or omissions by you in connection with or as a result of your wallet  being compromised.

This Agreement is not intended to, and does not, create or impose any fiduciary duties on us. To the fullest extent permitted by law, you acknowledge and agree that we owe no fiduciary duties or liabilities to you or any other party, and that to the extent any such duties or liabilities may exist at law or in equity, those duties and liabilities are hereby irrevocably disclaimed, waived, and eliminated. You further agree that the only duties and obligations that we owe you are those set out expressly in this Agreement.

### 4.4 Compliance and Tax Obligations

One or more of our Products may not be available or appropriate for use in your jurisdiction. By accessing or using any of our Products, you agree that you are solely and entirely responsible for compliance with all laws and regulations that may apply to you.

Specifically, your use of our Products or the Protocol may result in various tax consequences, such as income or capital gains tax, value-added tax, goods and services tax, or sales tax in certain jurisdictions.

It is your responsibility to determine whether taxes apply to any transactions you initiate or receive and, if so, to report and/or remit the correct tax to the appropriate tax authority.

### 4.5 Release of Claims

You expressly agree that you assume all risks in connection with your access and use of any of our Products. You further expressly waive and release us from any and all liability, claims, causes of action, or damages arising from or in any way relating to your use of any of our Products. If you are a California resident, you waive the benefits and protections of California Civil Code § 1542, which provides: "\[a] general release does not extend to claims that the creditor or releasing party does not know or suspect to exist in his or her favor at the time of executing the release and that, if known by him or her, would have materially affected his or her settlement with the debtor or released party."

## 5. DISCLAIMERS

### 5.1 ASSUMPTION OF RISK -- GENERALLY

BY ACCESSING AND USING ANY OF OUR PRODUCTS, YOU REPRESENT THAT YOU ARE FINANCIALLY AND TECHNICALLY SOPHISTICATED ENOUGH TO UNDERSTAND THE INHERENT RISKS ASSOCIATED WITH USING CRYPTOGRAPHIC AND BLOCKCHAIN-BASED SYSTEMS, AND THAT YOU HAVE A WORKING KNOWLEDGE OF THE USAGE AND INTRICACIES OF DIGITAL ASSETS SUCH AS FLOW, SO-CALLED STABLECOINS, AND OTHER DIGITAL TOKENS SUCH AS THOSE FOLLOWING THE FLOW FUNGIBLE TOKEN STANDARD.

IN PARTICULAR, YOU UNDERSTAND THAT THE MARKETS FOR THESE DIGITAL ASSETS ARE NASCENT AND HIGHLY VOLATILE DUE TO RISK FACTORS INCLUDING, BUT NOT LIMITED TO, ADOPTION, SPECULATION, TECHNOLOGY, SECURITY, AND REGULATION. YOU UNDERSTAND THAT ANYONE CAN CREATE A TOKEN, INCLUDING FAKE VERSIONS OF EXISTING TOKENS AND TOKENS THAT FALSELY CLAIM TO REPRESENT PROJECTS, AND ACKNOWLEDGE AND ACCEPT THE RISK THAT YOU MAY MISTAKENLY TRADE THOSE OR OTHER TOKENS. SO-CALLED STABLECOINS MAY NOT BE AS STABLE AS THEY PURPORT TO BE, MAY NOT BE FULLY OR ADEQUATELY COLLATERALIZED, AND MAY BE SUBJECT TO PANICS AND RUNS.

FURTHER, YOU UNDERSTAND THAT SMART CONTRACT TRANSACTIONS AUTOMATICALLY EXECUTE AND SETTLE, AND THAT BLOCKCHAIN-BASED TRANSACTIONS ARE IRREVERSIBLE WHEN CONFIRMED. YOU ACKNOWLEDGE AND ACCEPT THAT THE COST AND SPEED OF TRANSACTING WITH CRYPTOGRAPHIC AND BLOCKCHAIN-BASED SYSTEMS SUCH AS FLOW ARE VARIABLE AND MAY INCREASE DRAMATICALLY AT ANY TIME. YOU FURTHER ACKNOWLEDGE AND ACCEPT THE RISK OF SELECTING TO TRADE IN EXPERT MODES, WHICH CAN EXPOSE YOU TO POTENTIALLY SIGNIFICANT PRICE SLIPPAGE AND HIGHER COSTS.

IF YOU ACT AS A LIQUIDITY PROVIDER TO THE PROTOCOL THROUGH THE INTERFACE, YOU UNDERSTAND THAT YOUR DIGITAL ASSETS MAY LOSE SOME OR ALL OF THEIR VALUE WHILE THEY ARE SUPPLIED TO THE PROTOCOL THROUGH THE INTERFACE DUE TO THE FLUCTUATION OF PRICES OF TOKENS IN A TRADING PAIR OR LIQUIDITY POOL.

FINALLY, YOU UNDERSTAND THAT WE DO NOT CREATE, OWN, OR OPERATE CROSS-CHAIN BRIDGES AND WE DO NOT MAKE ANY REPRESENTATION OR WARRANTY ABOUT THE SAFETY OR SOUNDNESS OF ANY CROSS-CHAIN BRIDGE.

IN SUMMARY, YOU ACKNOWLEDGE THAT WE ARE NOT RESPONSIBLE FOR ANY OF THESE VARIABLES OR RISKS, DO NOT OWN OR CONTROL THE PROTOCOL, AND CANNOT BE HELD LIABLE FOR ANY RESULTING LOSSES THAT YOU EXPERIENCE WHILE ACCESSING OR USING ANY OF OUR PRODUCTS. ACCORDINGLY, YOU UNDERSTAND AND AGREE TO ASSUME FULL RESPONSIBILITY FOR ALL OF THE RISKS OF ACCESSING AND USING THE INTERFACE TO INTERACT WITH THE PROTOCOL.\*\*

### 5.2 NO WARRANTIES

EACH OF OUR PRODUCTS ARE PROVIDED ON AN "AS IS" AND "AS AVAILABLE" BASIS. TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM ANY REPRESENTATIONS AND WARRANTIES OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU ACKNOWLEDGE AND AGREE THAT YOUR USE OF EACH OF OUR PRODUCTS IS AT YOUR OWN RISK. WE DO NOT REPRESENT OR WARRANT THAT ACCESS TO ANY OF OUR PRODUCTS WILL BE CONTINUOUS, UNINTERRUPTED, TIMELY, OR SECURE; THAT THE INFORMATION CONTAINED IN ANY OF OUR PRODUCTS WILL BE ACCURATE, RELIABLE, COMPLETE, OR CURRENT; OR THAT ANY OF OUR PRODUCTS WILL BE FREE FROM ERRORS, DEFECTS, VIRUSES, OR OTHER HARMFUL ELEMENTS. NO ADVICE, INFORMATION, OR STATEMENT THAT WE MAKE SHOULD BE TREATED AS CREATING ANY WARRANTY CONCERNING ANY OF OUR PRODUCTS. WE DO NOT ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY ADVERTISEMENTS, OFFERS, OR STATEMENTS MADE BY THIRD PARTIES CONCERNING ANY OF OUR PRODUCTS.

SIMILARLY, THE PROTOCOL IS PROVIDED "AS IS", AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND. ALTHOUGH WE CONTRIBUTED TO THE INITIAL CODE FOR THE PROTOCOL, WE DO NOT PROVIDE, OWN, OR CONTROL THE PROTOCOL, WHICH IS RUN AUTONOMOUSLY WITHOUT ANY HEADCOUNT BY SMART CONTRACTS DEPLOYED ON VARIOUS BLOCKCHAINS. NO DEVELOPER OR ENTITY INVOLVED IN CREATING THE PROTOCOL WILL BE LIABLE FOR ANY CLAIMS OR DAMAGES WHATSOEVER ASSOCIATED WITH YOUR USE, INABILITY TO USE, OR YOUR INTERACTION WITH OTHER USERS OF, THE PROTOCOL, INCLUDING ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR LOSS OF PROFITS, CRYPTOCURRENCIES, TOKENS, OR ANYTHING ELSE OF VALUE. WE DO NOT ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY ADVERTISEMENTS, OFFERS, OR STATEMENTS MADE BY THIRD PARTIES CONCERNING ANY OF OUR PRODUCTS.

ANY PAYMENTS OR FINANCIAL TRANSACTIONS THAT YOU ENGAGE IN WILL BE PROCESSED VIA AUTOMATED SMART CONTRACTS. ONCE EXECUTED, WE HAVE NO CONTROL OVER THESE PAYMENTS OR TRANSACTIONS, NOR DO WE HAVE THE ABILITY TO REVERSE ANY PAYMENTS OR TRANSACTIONS.

### 5.3 NO INVESTMENT ADVICE&#x20;

WE MAY PROVIDE INFORMATION ABOUT TOKENS IN OUR PRODUCTS SOURCED FROM THIRD-PARTY DATA PARTNERS THROUGH FEATURES SUCH AS RARITY SCORES, TOKEN EXPLORER OR TOKEN LISTS (WHICH INCLUDES THE INCREMENT LABS DEFAULT TOKEN LIST). WE MAY ALSO PROVIDE WARNING LABELS FOR CERTAIN TOKENS. THE PROVISION OF INFORMATIONAL MATERIALS DOES NOT MAKE TRADES IN THOSE TOKENS SOLICITED; WE ARE NOT ATTEMPTING TO INDUCE YOU TO MAKE ANY PURCHASE AS A RESULT OF INFORMATION PROVIDED. ALL SUCH INFORMATION PROVIDED BY ANY OF OUR PRODUCTS IS FOR INFORMATIONAL PURPOSES ONLY AND SHOULD NOT BE CONSTRUED AS INVESTMENT ADVICE OR A RECOMMENDATION THAT A PARTICULAR TOKEN IS A SAFE OR SOUND INVESTMENT. YOU SHOULD NOT TAKE, OR REFRAIN FROM TAKING, ANY ACTION BASED ON ANY INFORMATION CONTAINED IN ANY OF OUR PRODUCTS. BY PROVIDING TOKEN INFORMATION FOR YOUR CONVENIENCE, WE DO NOT MAKE ANY INVESTMENT RECOMMENDATIONS TO YOU OR OPINE ON THE MERITS OF ANY TRANSACTION OR OPPORTUNITY. YOU ALONE ARE RESPONSIBLE FOR DETERMINING WHETHER ANY INVESTMENT, INVESTMENT STRATEGY OR RELATED TRANSACTION IS APPROPRIATE FOR YOU BASED ON YOUR PERSONAL INVESTMENT OBJECTIVES, FINANCIAL CIRCUMSTANCES, AND RISK TOLERANCE.

## 6. Indemnification

You agree to hold harmless, release, defend, and indemnify us and our officers, directors, employees, contractors, agents, affiliates, and subsidiaries from and against all claims, damages, obligations, losses, liabilities, costs, and expenses arising from: (a) your access and use of any of our Products; (b) your violation of any term or condition of this Agreement, the right of any third party, or any other applicable law, rule, or regulation; (c) any other party's access and use of any of our Products with your assistance or using any device or account that you own or control; and (d) any dispute between you and (i) any other user of any of the Products or (ii) any of your own customers or users.

## 7. Limitation of Liability

UNDER NO CIRCUMSTANCES SHALL WE OR ANY OF OUR OFFICERS, DIRECTORS, EMPLOYEES, CONTRACTORS, AGENTS, AFFILIATES, OR SUBSIDIARIES BE LIABLE TO YOU FOR ANY INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE, DATA, OR OTHER INTANGIBLE PROPERTY, ARISING OUT OF OR RELATING TO ANY ACCESS OR USE OF OR INABILITY TO ACCESS OR USE ANY OF THE PRODUCTS, NOR WILL WE BE RESPONSIBLE FOR ANY DAMAGE, LOSS, OR INJURY RESULTING FROM HACKING, TAMPERING, OR OTHER UNAUTHORIZED ACCESS OR USE OF ANY OF THE PRODUCTS OR THE INFORMATION CONTAINED WITHIN IT, WHETHER SUCH DAMAGES ARE BASED IN CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY, OR OTHERWISE, ARISING OUT OF OR IN CONNECTION WITH AUTHORIZED OR UNAUTHORIZED USE OF ANY OF THE PRODUCTS, EVEN IF AN AUTHORIZED REPRESENTATIVE OF INCREMENT LABS HAS BEEN ADVISED OF OR KNEW OR SHOULD HAVE KNOWN OF THE POSSIBILITY OF SUCH DAMAGES. WE ASSUME NO LIABILITY OR RESPONSIBILITY FOR ANY: (A) ERRORS, MISTAKES, OR INACCURACIES OF CONTENT; (B) PERSONAL INJURY OR PROPERTY DAMAGE, OF ANY NATURE WHATSOEVER, RESULTING FROM ANY ACCESS OR USE OF THE INTERFACE; (C) UNAUTHORIZED ACCESS OR USE OF ANY SECURE SERVER OR DATABASE IN OUR CONTROL, OR THE USE OF ANY INFORMATION OR DATA STORED THEREIN; (D) INTERRUPTION OR CESSATION OF FUNCTION RELATED TO ANY OF THE PRODUCTS; (E) BUGS, VIRUSES, TROJAN HORSES, OR THE LIKE THAT MAY BE TRANSMITTED TO OR THROUGH THE INTERFACE; (F) ERRORS OR OMISSIONS IN, OR LOSS OR DAMAGE INCURRED AS A RESULT OF THE USE OF, ANY CONTENT MADE AVAILABLE THROUGH ANY OF THE PRODUCTS; AND (G) THE DEFAMATORY, OFFENSIVE, OR ILLEGAL CONDUCT OF ANY THIRD PARTY.

WE HAVE NO LIABILITY TO YOU OR TO ANY THIRD PARTY FOR ANY CLAIMS OR DAMAGES THAT MAY ARISE AS A RESULT OF ANY PAYMENTS OR TRANSACTIONS THAT YOU ENGAGE IN VIA ANY OF OUR PRODUCTS, OR ANY OTHER PAYMENT OR TRANSACTIONS THAT YOU CONDUCT VIA ANY OF OUR PRODUCTS. EXCEPT AS EXPRESSLY PROVIDED FOR HEREIN, WE DO NOT PROVIDE REFUNDS FOR ANY PURCHASES THAT YOU MIGHT MAKE ON OR THROUGH ANY OF OUR PRODUCTS.

WE MAKE NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, ABOUT LINKED THIRD PARTY SERVICES, THE THIRD PARTIES THEY ARE OWNED AND OPERATED BY, THE INFORMATION CONTAINED ON THEM, ASSETS AVAILABLE THROUGH THEM, OR THE SUITABILITY, PRIVACY, OR SECURITY OF THEIR PRODUCTS OR SERVICES. YOU ACKNOWLEDGE SOLE RESPONSIBILITY FOR AND ASSUME ALL RISK ARISING FROM YOUR USE OF THIRD-PARTY SERVICES, THIRD-PARTY WEBSITES, APPLICATIONS, OR RESOURCES.  WE SHALL NOT BE LIABLE UNDER ANY CIRCUMSTANCES FOR DAMAGES ARISING OUT OF OR IN ANY WAY RELATED TO SOFTWARE, PRODUCTS, SERVICES, AND/OR INFORMATION OFFERED OR PROVIDED BY THIRD-PARTIES AND ACCESSED THROUGH ANY OF OUR PRODUCTS.

SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. IN NO EVENT SHALL OUR TOTAL LIABILITY TO YOU FOR ALL DAMAGES (OTHER THAN AS MAY BE REQUIRED BY APPLICABLE LAW IN CASES INVOLVING PERSONAL INJURY) EXCEED THE AMOUNT OF ONE HUNDRED U.S. DOLLARS ($100.00 USD) OR ITS EQUIVALENT IN THE LOCAL CURRENCY OF THE APPLICABLE JURISDICTION.

THE FOREGOING DISCLAIMER WILL NOT APPLY TO THE EXTENT PROHIBITED BY LAW.

## 8. Miscellaneous&#x20;

### 8.1 Entire Agreement

These terms constitute the entire agreement between you and us with respect to the subject matter hereof. This Agreement supersedes any and all prior or contemporaneous written and oral agreements, communications and other understandings (if any) relating to the subject matter of the terms.

### 8.2 Assignment

You may not assign or transfer this Agreement, by operation of law or otherwise, without our prior written consent. Any attempt by you to assign or transfer this Agreement without our prior written consent shall be null and void. We may freely assign or transfer this Agreement. Subject to the foregoing, this Agreement will bind and inure to the benefit of the parties, their successors and permitted assigns.

### 8.3 Rewards

In connection with your historic or current use of one or more of our Products, we may provide you certain incentives, prizes or rewards for completing certain activities, such as completing a certain number of transactions ("User Rewards"). Details regarding the criteria for earning a reward will be described within the applicable Product or official Increment Labs documentation. Upon satisfaction of the criteria for obtaining a reward and subject to your compliance with the associated rewards terms, this Agreement, and applicable law — to be determined exclusively by Increment Labs — we will use commercially reasonable efforts to promptly transfer the earned reward to the digital wallet that you designate or have connected to the applicable Product. We reserve the right to change, modify, discontinue or cancel any rewards programs (including the frequency and criteria for earning such User Rewards), at any time and without notice to you.

### 8.4 Not Registered with the SEC or Any Other Agency

We are not registered with the U.S. Securities and Exchange Commission as a national securities exchange or in any other capacity. You understand and acknowledge that we do not broker trading orders on your behalf. We also do not facilitate the execution or settlement of your trades, which occur entirely on public distributed blockchains like Ethereum. As a result, we do not (and cannot) guarantee market best pricing or best execution through our Products or when using our Auto Routing feature, which routes trades across liquidity pools on the Protocol only. Any references in a Product to "best price" does not constitute a representation or warranty about pricing available through such Product, on the Protocol, or elsewhere.

### 8.5. Notice

We may provide any notice to you under this Agreement using commercially reasonable means, including using public communication channels. Notices we provide by using public communication channels will be effective upon posting.

### 8.6 Severability

If any provision of this Agreement shall be determined to be invalid or unenforceable under any rule, law, or regulation of any local, state, or federal government agency, such provision will be changed and interpreted to accomplish the objectives of the provision to the greatest extent possible under any applicable law and the validity or enforceability of any other provision of this Agreement shall not be affected.


# Privacy Policy

Last modified: July 10, 2023

This Privacy Policy (the “Policy”) explains how “Increment Labs” (the “Company”, “we”, “us” or “our”) collects, uses, and shares data in connection with the IncrementFi web app ([app.increment.fi](https://app.increment.fi), [increment.fi](https://increment.fi)) website and all of our other properties, products, and services (the “Services”). Your use of the Services is subject to this Policy as well as our [Terms of Service](/miscs/term-of-service).&#x20;

## High Level Summary

* Increment Labs is an incorporated company based in the British Virgin Islands that operates <https://app.increment.fi> among other products and services. Increment Labs complies with British Virgin Islands’ laws and regulations.
* Increment products are a censorship-resistant set of smart contracts deployed on the Flow blockchain. It is not governed by Increment Labs.
* Increment Labs does not collect and store personal data, such as first name, last name, street address, date of birth, email address, or IP address, in connection with your use of the Services.
* Increment Labs collects non-identifiable data, such as public on-chain data, and limited off-chain data like device type, browser version, etc. This is to help drive production vision, not track users.
* If you specifically sign up to receive emails from us, we will store your email address to allow us to send you those emails. You can unsubscribe at any time. We will not attempt to link your email address to your wallet address, IP address, or other personal data.
* Increment Labs continues to explore methods to further protect consumers' privacy, such as opt-out prompts, migrating to privacy-centric tooling and deploying proxies to anonymize network traffic.
* Users are empowered to explore client-side privacy techniques and tools.
* Any material changes to privacy will be reflected in an updated privacy policy.

## Data We Collect

Privacy is central to everything we do at the Company. And we've enshrined transparency as one of our Company values. Accordingly, we aspire to be transparent about what little data we do collect. We do not maintain user accounts and do not collect and store personal data, such as your name or internet protocol (“IP”) address. When you interact with the Services, we collect only:

* Publicly-available blockchain data. When you connect your non-custodial blockchain wallet to the Services, we collect and log your publicly-available blockchain address to learn more about your use of the Services and to screen your wallet for any prior illicit activity. We screen your wallet using intelligence provided by leading blockchain analytics providers. Note that blockchain addresses are publicly-available data that are not created or assigned by us or any central party, and by themselves are not personally identifying.
* Information from localStorage and other tracking technologies. We and our third-party services providers may access and collect information from localStorage, mobile deviceID, cookies, web beacons, and other similar technologies to provide and personalize the Services and features of the Services for you across sessions. For example, we may use this information to remember tokens you import, star, or add to your shopping bag. We may also use this information to learn about your preferences, your use of the Services, and our interactions with you. Information we collect from these technologies may include things such as browser type, referring/exit pages, operating system, device or browser language, and other device information. We group and analyze these user journeys collectively, in the aggregate, to improve our product user experience.
* Information from other sources. We may receive information about your wallet address or transactions made through the Services from our service providers in order to comply with our legal obligations and prevent the use of our Services in connection with fraudulent or other illicit activities.
* Survey or usability information. If you participate in a survey or usability study with us, we will record any biographical information you directly provide to us (for example, your name, email, and job title), the responses you provide to us, and your interactions with the Services.
* Correspondence. We will receive any communications and information you provide directly to us via email, customer support, social media, or another support channel (such as Twitter or Discord), or when you participate in any surveys or questionnaires.
* Biographical information. If you apply for a job with us, we collect all information provided through our Jobs form, including name, email phone, work and immigration status, and any other resume, cover letter, or free form text you include.
* Information you specifically provide us. If you specifically provide us with information (such as your email address), we may use that information for the purposes described when you provide it to us. We will not attempt to link any information you provide to your wallet address, IP address, or other personal data. You do not need to provide us with any personal data to use the Services.

## How We Use Data

We use the data we collect in accordance with your instructions, including any applicable terms in our [Terms of Service](/miscs/term-of-service), and as required by law. We may also use data for the following purposes:

* Providing the Services. We use the data we collect to provide, maintain, customize and improve our Services and features of our Services.
* Customer support. We may use information to provide customer support for and answer inquiries about the Services.
* Safety and security. We may use data to protect against, investigate, and stop fraudulent, unauthorized, or illegal activity. We may also use it to address security risks, solve potential security issues such as bugs, enforce our agreements, and protect our users and Company.
* Legal compliance. We may use the information we collect as needed or requested by regulators, government entities, and law enforcement to comply with applicable laws and regulations.
* Aggregated data. We may use some of the information we collect or access to compile aggregated data that helps us learn more about how users use the Services and where we can improve your experience.

## How We Share Data

We may share or disclose the data we collect:

* With service providers. We may share your information with our service providers and vendors to assist us in providing, delivering, and improving the Services. For example, we may share your wallet address with service providers like Quicknode and Cloudflare to provide technical infrastructure services, your wallet address with blockchain analytics providers to detect, prevent, and mitigate financial crime and other illicit or harmful activities, and your activity on our social media pages with our analytics provider to learn more about you interact with us and the Services.
* To comply with our legal obligations. We may share your data in the course of litigation, regulatory proceedings, compliance measures, and when compelled by subpoena, court order, or other legal procedure. We may also share data when we believe it is necessary to prevent harm to our users, our Company, or others, and to enforce our agreements and policies, including our Terms of Service.
* Safety and Security. We may share data to protect against, investigate, and stop fraudulent, unauthorized, or illegal activity. We may also use it to address security risks, solve potential security issues such as bugs, enforce our agreements, and protect our users, Company, and ecosystem.
* Business changes. We may transfer or share data to another entity in the event of a merger, acquisition, bankruptcy, dissolution, reorganization, asset or stock sale, or other business transaction.
* With your consent. We may share your information any other time you provide us with your consent to do so.

We do not share your information with any third parties for any marketing purposes whatsoever.

## Third Party Cookies

We use services provided by Google and other third parties that use tracking technology such as cookies, deviceID, and localStorage, to collect information about your use of the Services and our interactions with you. You can opt out of having your online activity and device data collected through these third-party services, including by:

* Blocking cookies in your browser by following the instructions in your browser settings. For more information about cookies, including how to see the cookies on your device, manage them, and delete them, visit [www.allaboutcookies.org](http://www.allaboutcookies.org/).
* Blocking or limiting the use of your advertising ID on your mobile device through the device settings.
* Using privacy plug-ins or browsers. Certain browsers and browser extensions can be configured to block third-party cookies and trackers.
* Using the platform opt-out provided by Google at [https://adssettings.google.com](https://adssettings.google.com/). You can learn more about how Google uses your information by reviewing Google’s privacy policy at <https://policies.google.com/privacy>.
* Using advertising industry opt-out tools on each device or browser where you use the Services, available at [http://optout.aboutads.info](http://optout.aboutads.info/) and [http://optout.networkadvertising.org](http://optout.networkadvertising.org/).

## Third-Party Links and Sites

We may integrate technologies operated or controlled by other parties into parts of the Services. For example, the Services may include links that hyperlink to websites, platforms, and other services not operated or controlled by us. Please note that when you interact with these other parties, including when you leave the Site, those parties may independently collect information about you and solicit information from you. You can learn more about how those parties collect and use your data by consulting their privacy policies and other terms.

## Security

We implement and maintain reasonable administrative, physical, and technical security safeguards to help protect data from loss, theft, misuse, unauthorized access, disclosure, alteration, and destruction. Nevertheless, transmission via the internet is not completely secure and we cannot guarantee the security of information about you. You are responsible for all of your activity on the Services, including the security of your blockchain network addresses, cryptocurrency wallets, and their cryptographic keys.

## Age Requirements

The Services are intended for a general audience and are not directed at children. We do not knowingly receive personal information (as defined by the U.S. Children’s Privacy Protection Act, or “COPPA”) from children. If you believe we have received personal information about a child under the age of 18, please contact us at <contact@increment.fi>.

## Additional Notice to California Residents (“CCPA Notice”)

The California Consumer Privacy Act of 2018 (“CCPA”) requires certain businesses to provide a CCPA Notice to California residents to explain how we collect, use, and share their personal information, and the rights and choices we offer California residents regarding our handling of their information.

* Privacy Practices. We do not “sell” personal information as defined under the CCPA. Please review the “Sharing and Disclosure of Information” section above for further details about the categories of parties with whom we share information.
* Privacy Rights. The CCPA gives individuals the right to request information about how we have collected, used, and shared your personal information. It also gives you the right to request a copy of any information we may maintain about you. You may also ask us to delete any personal information that we may have received about you. Please note that the CCPA limits these rights, for example, by prohibiting us from providing certain sensitive information in response to access requests and limiting the circumstances under which we must comply with a deletion request. We will respond to requests for information, access, and deletion only to the extent we are able to associate, with a reasonable effort, the information we maintain with the identifying details you provide in your request. If we deny the request, we will communicate the decision to you. You are entitled to exercise the rights described above free from discrimination.
* Submitting a Request. You can submit a request for information, access, or deletion to <contact@increment.fi>.
* Identity Verification. The CCPA requires us to collect and verify the identity of any individual submitting a request to access or delete personal information before providing a substantive response.
* Authorized Agents. California residents can designate an “authorized agent” to submit requests on their behalf. We will require the authorized agent to have a written authorization confirming their authority.

## Disclosures for European Union Data Subjects

We process personal data for the purposes described in the section titled “How We Use Data” above. Our bases for processing your data include: (i) you have given consent to the process to us or our service provides for one or more specific purposes; (ii) processing is necessary for the performance of a contract with you; (iii) processing is necessary for compliance with a legal obligation; and/or (iv) processing is necessary for the purposes of the legitimate interested pursued by us or a third party, and your interests and fundamental rights and freedoms do not override those interests.

Your rights under the General Data Protection Regulations (“GDPR”) include the right to (i) request access and obtain a copy of your personal data, (ii) request rectification or erasure of your personal data, (iii) object to or restrict the processing of your personal data; and (iv) request portability of your personal data. Additionally, you may withdraw your consent to our collection at any time. Nevertheless, we cannot edit or delete information that is stored on a particular blockchain. Information such as your transaction data, blockchain wallet address, and assets held by your address that may be related to the data we collect is beyond our control.

To exercise any of your rights under the GDPR, please contact us at <contact@increment.fi>. We may require additional information from you to process your request. Please note that we may retain information as necessary to fulfill the purpose for which it was collected and may continue to do so even after a data subject request in accordance with our legitimate interests, including to comply with our legal obligations, resolve disputes, prevent fraud, and enforce our agreements.

## Changes to this Policy

If we make material changes to this Policy, we will notify you via the Services. Nevertheless, your continued use of the Services reflects your periodic review of this Policy and other Company terms, and indicates your consent to them.

## Contact Us

If you have any questions about this Policy or how we collect, use, or share your information, please contact us at <contact@increment.fi>.


