# What is QuipuSwap?

[QuipuSwap](https://quipuswap.com) is an ecosystem built around Tezos-based AMM (automated market-maker) that provides infrastructural solutions for the Tezos network.

AMM protocol powers decentralized exchange solutions by creating Liquidity Pools instead of the traditional order books that are used in centralized exchanges.

Learn more about AMM and how it works from [this video](https://youtu.be/1PbZMudPP5E).

Also, from [this video](https://www.youtube.com/watch?v=cizLhxSKrAc), you will learn how Liquidity pools work and why you may receive a different number of tokens for the same amount of shares (liquidity pool tokens).

If you want to learn how you can earn with QuipuSwap, please read [this article](https://madfish.crunch.help/quipu-swap/i-have-added-liquidity-to-quipu-swap-how-much-will-i-earn-what-is-the-apy-of-your-dex).


# Participants

The QuipuSwap community is composed of five primary user roles: liquidity providers, traders, bakers, voters, and developers.

**Liquidity providers** create liquidity pools and provide them with Tez and the corresponding FA1.2 and FA2 tokens.

**Traders** earn trading fees and may participate in our liquidity mining programs. Traders exchange one token for another.

**Bakers** manage individual pool’s assets when it comes to baking in Tez/token pools and encourage liquidity providers to vote for them by, for example, offering them better rewards.

**Voters** stake their shares to vote for their chosen baker (that they feel is contributing to a system’s wellbeing and maximizing the baking rewards) or against a malicious one. Voting only happens in Tez/token pools.

**Developers** build solutions to directly integrate QuipuSwap smart contracts to power new and exciting interactions with tokens, trading interfaces, retail experiences, etc.

This list is not exhaustive. As the protocol develops, more roles such as **governor** or **liquidity** miner might be introduced.

In general, interactions between the roles create a positive feedback loop, allowing for new economic opportunities in the Tezos ecosystem and paving the way to more complex solutions.


# QuipuSwap subprojects


# QuipuSwap Farms

Farms is a part of the growing QuipuSwap ecosystem which main aim is increasing of liquidity in all QuipuSwap pools. Smart contracts for QuipuSwap farms are built, internally audited, and deployed in mainnet. Interface fees are supported, incentivising other platforms to integrate farms into their interface.

There are two options for farming contracts:

* Staking LPs or single assets to earn QUIPU.
* Staking LPs or single assets to earn other tokens.

GitHub repository: <https://github.com/madfish-solutions/quipuswap-farming>


# Quipuswap Stable DEX

Stable DEX is the upcoming QuipuSwap feature for price-efficient and low-risk stablecoin trading. We intend to create a solution for the Tezos ecosystem akin to that Curve and Ellipsis have created for Ethereum and BSC, respectively.

GitHub repository: <https://github.com/madfish-solutions/quipuswap-stable-core>


# Token to Token Swaps

Previously QuipuSwap used the formula TOKEN A→TEZ→TOKEN B to exchange one Tezos-based token for another. QuipuSwap Token2Token protocol grants access to token-to-token pools in which anyone can create and add liquidity.

This solution reduces the costs for token-to-token transactions. Additionally, token-to-token pool creation is manyfold cheaper.

GitHub repository: <https://github.com/madfish-solutions/quipuswap-token2token-core>


# Governance (text-only)

QuipuSwap is on its way to a decentralized governance.

For now QUIPU token owners can participate in the text-only governance. By staking their QUIPU they will be able to create and vote for proposals. If the quorum is reached the decision will be implemented.

GitHub repository: <https://github.com/madfish-solutions/quipuswap-governance>


# Install Wallet

Any cryptocurrency wallet that supports Tezos blockchain dapps can be connected to [QuipuSwap](https://quipuswap.com).

If you do not have a Tezos wallet installed yet, we recommend using the [Temple wallet](https://templewallet.com). Temple is developed and maintained by our team.

In the following video, you will see the entire installation procedure:

{% embed url="<https://www.youtube.com/watch?v=S8_tL8PfCts>" %}


# How to get TEZ

Tezos, Tez, or XTZ is the native Tezos blockchain coin that is used not only to purchase other assets but to pay all the fees within the Tezos network. You will need some Tez to start trading on QuipuSwap.

To buy Tez with fiat you can use any external exchange. Acquire XTZ and send them to your Tezos wallet.

If you already have some crypto assets, you can also use an in-built [Temple wallet feature](https://templewallet.com).

**Centralized approach**

Centralized exchanges require [KYC](https://en.wikipedia.org/wiki/Know_your_customer) but they are still the most reliable venue to buy crypto with fiat. Check [this page](https://coinmarketcap.com/currencies/tezos/markets/) for a list of exchanges that support Tezos. Pick an exchange, register an account, buy Tezos and send these tokens to your Tezos address.

We have a tutorial on how to [send XTZ from Binance to Temple wallet](https://madfish.crunch.help/temple-wallet/how-to-sent-tez-xtz-from-binance-to-the-temple-wallet). But the process should be similar whatever exchange you choose to use.

**Decentralized options**

If you want to buy TEZ using decentralized solutions then it’s better to use the in-build feature in [Atomex wallet](https://atomex.me). In this wallet, you may swap your BTC or LTC to Tezos.

Also, as we mentioned before, the Temple wallet has integrated a third-party service, [Exolix](https://exolix.com) exchange, that allows users to swap tokens from other blockchains into XTZ.

And read [this guide](https://madfish.crunch.help/temple-wallet/i-topped-up-tez-balance-via-temple-s-buy-tab-but-never-received-the-xtz-what-should-i-do) for troubleshooting.


# How to find my tokens

If you know that you were sent any amount of a certain token but it is not shown in your wallet, there are several ways to go about it.

1. Find the token contract address and add it manually to the wallet. For instance, in the Temple wallet, you need to use the Manage section and click the “Add Token” button. [Read a detailed guide here](https://youtu.be/GoJPvlrHvQE).
2. If you do not know the contract address of the token, you can visit the [blockchain explorer](https://tzkt.io) page, paste your account address and see all assets owned by this account under the Tokens tab.


# Connect wallet

To connect a wallet to QuipuSwap you only need to click the Connect button and choose the wallet and the account you will use to interact with the platform.

![](https://3452914001-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZECuZ1tNwwhpxyp28pLs%2Fuploads%2F2MHnulYjP6SOm8LbG210%2Fimage.png?alt=media\&token=63fa8e38-c299-4d8a-8d01-8750a83209e9)


# FAQ

**The most common questions about QuipuSwap usage:**

[What is QuipuSwap governance token QUIPU?](https://madfish.crunch.help/quipu-swap/faq-quipu-governance-token)

[I have added Liquidity to QuipuSwap; how much will I earn? What is the APY of your DEX?](https://madfish.crunch.help/quipu-swap/i-have-added-liquidity-to-quipu-swap-how-much-will-i-earn-what-is-the-apy-of-your-dex)

[What is baking and how do I bake on QuipuSwap?](https://madfish.crunch.help/quipu-swap/what-is-baking-and-how-do-i-bake-on-quipu-swap)

[I am a developer, what should I know?](https://madfish.crunch.help/quipu-swap/quipu-swap-for-developers)

[How to Add Liquidity to an existing Liquidity Pool on QuipuSwap?](https://madfish.crunch.help/quipu-swap/how-to-add-liquidity-to-the-existing-liquidity-pool-on-quipu-swap)

[How to Add a new Liquidity Pool to QuipuSwap?](https://madfish.crunch.help/quipu-swap/how-to-add-a-new-liquidity-pool-to-quipu-swap)

[How to get baking rewards on QuipuSwap and Vote for a baker?](https://madfish.crunch.help/quipu-swap/how-to-get-trading-fees-and-baking-rewards-on-quipu-swap)

[I am trying to swap some tokens | add Liquidity but I'm constantly receiving errors. What should I do?](https://madfish.crunch.help/quipu-swap/i-am-trying-to-swap-some-tokens-but-i-m-constantly-receving-errors)

**Do you have more questions?**

Visit our [Help Center](https://madfish.crunch.help) or ask your question in our [telegram](https://t.me/MadFishCommunity) or [discord](https://madfish.solutions/discord) community.


# Overview

[QuipuSwap](https://quipuswap.com) is an ecosystem built around Tezos-based AMM (automated market-maker) that provides infrastructural solutions for the Tezos network.

**QuipuSwap ecosystem** will eventually include a Tezos AMM DEX, a separate stablecoin DEX, a cross-chain bridge, farms.

QuipuSwap has a native token [QUIPU](https://madfish.crunch.help/quipu-swap/faq-quipu-governance-token), used in governance and certain internal payments.


# Types of the exchange (Token/TEZ, Token/Token)

QuipuSwap supports two types of liquidity pools: **XTZ-Token** and **Token-Token**.

Previously, a direct token to token swap was not possible and had to be conducted with an extra step (Token-TEZ-Token). Our new Token-Token solution has been extensively tested and audited and is ready for use.


# How to use the DEX

In this section you will learn the most common QuipuSwap usage cases, for more information - visit our [Help center](https://madfish.crunch.help).


# Trade

Swapping Tezos-based tokens is the main feature of QuipuSwap.

Go to[ quipuswap.com](https://quipuswap.com), and click on the **Swap** tab:

![](https://ucarecdn.com/7149bada-34b3-47b7-8158-e56f39610fd4/image.png)

Connect your wallet and choose the tokens and the amounts to exchange:

![](https://ucarecdn.com/d239dea7-753d-46c5-9634-065687d2dc66/image.png)

Press the **Swap** button and confirm the transaction in your wallet. If you have any errors, check these help guides:

[I am trying to swap some tokens | add Liquidity but I'm constantly receiving errors. What should I do?](https://madfish.crunch.help/quipu-swap/i-am-trying-to-swap-some-tokens-but-i-m-constantly-receving-errors)

[The list of the wallet transaction statuses: errors and explanations](https://madfish.crunch.help/temple-wallet/the-list-of-the-transaction-statuses-errors-and-explanations).


# How to add liquidity to an existing liquidity pool

1\. Log into [QuipuSwap](https://quipuswap.com) via Tezos dApp wallet. We recommend using the [Temple wallet](https://templewallet.com).

2\. Visit the "Liquidity" section

3\. Click the "Add" tab

4\. Select Tokens that you want to add to QuipuSwap

![](https://ucarecdn.com/76fd8cc5-296d-493f-adc7-0978e317c423/image.png)

5\. Choose the number of tokens that you want to invest and click the "Add" Button

![](https://ucarecdn.com/8e0d5eba-a98d-4201-8923-b97d6ed06edd/image.png)

In case you don't see your token in the dropdown list you may add the token contract address to the search field and find this token.

![](https://ucarecdn.com/e4240f84-0d29-49b1-94b8-8cb120e52c08/image.png)

6\. Confirm this operation in your wallet and wait. Usually, you need to wait one minute to get a confirmation.

![](https://ucarecdn.com/38eecc1a-8720-42f4-8b2e-f505d4039941/image.png)

You will see the Success status on a popup window.

![](https://ucarecdn.com/bcf623b1-6fb4-4d2f-affa-bb599ce6db6b/image.png)


# How to create a new liquidity pool

1\. Visit the Liquidity Seсtion and choose the "Add" tab.

2\. Choose the tokens you want to add from the available list of addresses.

If such a pool does not really exist, you will see the notification **"Note! The pool doesn't exist. You will create a new one."**

![](https://ucarecdn.com/d96719a4-5d27-414b-aa2e-16799f76793a/image.png)

**Pay attention:** we don't recommend adding NFT tokens to QuipuSwap. Please, use specialized Marketplaces.

6\. Check the current market price of your tokens and their price ratio. It will be used as a starting point in the following operations.

7\. Click the "Add" button.

8\. Confirm this transaction in your wallet

![](https://ucarecdn.com/bf66c4b6-3630-4888-adc3-0400b0c85e59/image.png)

<mark style="color:red;">**Attention!**</mark>\*\* you will pay approximately 7XTZ (tez/token pools) or 0.2XTZ (token/token pools) as a storage fee for creating a Liquidity Pool. It's a one-time payment to store your smart contract in the Tezos blockchain.\*\*

That's all. Your Liquidity pool is created.


# How to remove liquidity

1\. Visit the Liquidity section,

2\. Choose the Remove tab

3\. Check how many shares you have and how much you will get in tokens.

![](https://ucarecdn.com/0e676760-837a-4432-baa6-77a3d60dea8c/image.png)

4\. Type in how many shares you would like to withdraw and in the Output field check how much you will get in tokens.

5\. Press Remove button and confirm the operation.


# How to vote for a baker

QuipuSwap allows you to delegate tokens at the same time as they are earning fee rewards in a liquidity pool. As tokens are added to the pool you automatically start receiving baking rewards. You do not have to cast a vote for a specific baker but you can do it if you have a favorite one or if you want to help spread delegated stakes more evenly.

NB: baking rewards are only poosible for Tez/Token pools, not Token/Token pools.

1\. Open the Voting section.

2\. Select the Vote tab and choose the token pool you would like to delegate LP tokens from.

![](https://ucarecdn.com/3c7b9c1e-690e-4a4f-8271-0d236f712115/image.png)

3\. Scroll down until you see the field marked as "Baker". Here you can either select a baker from a drop-down menu or enter his address manually.

4\. Decide how many shares (LP tokens) you want to lock in the voting contract and press Vote.

![](https://ucarecdn.com/f0c21312-1b35-4d9d-975a-740b7567c603/image.png)

That's it. Confirm this action and it's done.

You can vote for a different candidate any time but remember that each time the baker is changed, reward receiving process will reset.


# How to ban/veto a baker

LP holders on QuipuSwap can not only vote for specific bakers, but they may also use their LPs to veto a specific baker (i.e. ban him from being a baker in a pool for a time).

Generally, shareholders band together to veto a baker if they believe him to be unreliable or if he is overstaked.

Only a third of **staked** shares in the **Governance section** of the pool is required to veto a delegate.

The candidate is banned for 3 months and cannot receive votes during this period. Users can then withdraw their votes or restake them for other bakers. When a delegate is banned the second-best candidate becomes the delegate. But if the new delegate is banned afterward, the new delegate becomes None until any voting.

**Steps to cast a veto vote**:

1\. Go to the "Voting" section;

2\. Select the "Veto" tab;

3\. Enter the number of LP shares you want to vote against the delegate and click "Veto";

![](https://ucarecdn.com/c1eae783-310f-4d35-98d5-1af7d50dc961/image.png)

Once the transaction is confirmed, your votes will be counted.


# What is a Token?

A crypto token is a denomination of a cryptocurrency that allows its owner to participate in the economy of a given blockchain ecosystem.

Over the years there have been several interpretations of the word “token” in the crypto community but for the purposes of DeFi space, the most common meaning is any crypto asset that is not a blockchain’s native coin.

Tezos, Tez or XTZ is the native currency of the Tezos blockchain. All other cryptoassets that run atop Tezos blockchain are referred to as Tezos tokens. For example, QUIPU is a Tezos-based token.

Tokens differ from each other by the architecture (FA1.2 or FA2 format, fungible or NFT) and by the financial model (supply size, issuance rules, decimals number, etc.).


# What is the difference between FA1.2 and FA2 standards?

Any Tezos user can create a custom token of his own. To facilitate tokenization Tezos employs several token standards:

* **FA 1.2** is the more generic one, supporting only fungible tokens (akin to Ethereum's ERC-20). FA 2 is an advanced standard that also supports NFTs (similar to ERC-721 standard) and allows for multiple tokens to be managed on the same contract (like ERC-1155).
* **FA 2** is an advanced standard that also supports NFTs (similar to ERC-721 standard) and allows for multiple tokens to be managed on the same contract (like ERC-1155). NFT is a non-fungible token (FA2 standard). Each NFT is absolutely unique. This standard is most suited for minting digital collectible items, art objects, tickets, etc.

More information about differences between FA1.2 and FA2 standards you may find in our [educational article](https://story.madfish.solutions/do-we-need-a-new-tezos-token-standard/).

\\


# QUIPU Tokenomics

**Token Details:**

Token name and symbol: QUIPU

Contract address: KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb

Type: FA2

Total supply: 10 000 000

Decimals: 6

**Initial distribution:**

So far we have conducted two QUIPU airdrops as a thank you to our long-time users. A modest amount of tokens is reserved for future community rewards.

Circulated tokens after the second airdrop: 845 070 QUIPU

Circulated supply after the second airdrop is 8.4% (6% airdrops, 2.4% other funds)

**Token distribution model:**

![](https://3452914001-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZECuZ1tNwwhpxyp28pLs%2Fuploads%2FL7H0iT9UtITCBgoFoHdx%2Fimage.png?alt=media\&token=e53729c5-7358-494d-9d88-122971dfcf82)

**Token use cases:**

QUIPU tokens will be used in [QuipuSwap governance](https://github.com/madfish-solutions/quipuswap-governance) and as a means of payment for future additional QuipuSwap services.

More details about QuipuSwap tokenomics you may [find in this article](https://story.madfish.solutions/quipuswap-tokenomics-guide-quipu-learn-everything-about-our-governance-token/).


# Dex token edition


# Overview

Token-friendly AMM is the second automated liquidity protocol version implemented by the Quipuswap. Just as the initial exchange, it aims to empower decentralization, censorship resistance, and security.

The liquidity pool, or pair, is the core atom of the system. Despite the fact that the pool is just an abstraction inside the single contract and not the separate contract instance, each pool is managed separately, and such architecture enables the seamless multihop swaps.

Anyone can become a liquidity provider (LP) for a pool by depositing an equivalent value of each underlying token in return for LP tokens. The tokens represent the user’s share in the pool and can be withdrawn for the underlying assets at any time.

If the pair for certain FA1.2 or/and FA2 tokens doesn’t exist or all the liquidity was withdrawn, anyone can launch it by providing the initial liquidity.

AMM token edition is the automated market maker engine. It follows the exchange path provided by the caller and executes the exchanges, ensuring that the final output amount matches the user’s expectations. Under the hood, each swap is performed according to the constant product formula `x * y = k` which actually means that the product of tokens reserves should be the same before and after the swap.

In practice, Quipuswap applies a 0.30% fee to trades, which is added to reserves. As a result, each trade actually increases `k`, and thus reserves under the same amount of shares increase, allowing the LP providers to earn.

**The core difference from the Quipuswap v2:**

* token/token pools are supported;
* multihop pools are supported;
* all actions have a deadline;
* all the pools and reserves are stored on a single contract.

As mentioned, the solution consists of a single contract that acts as a pools register and automated market maker engine.


# Dex

The contract is responsible for launching new exchange pairs and serves as the automatic market maker engine. The contract manages pools for FA1.2/FA1.2, FA2/FA2 and FA2/FA1.2 tokens. The only instance of the pool for the same pair exists.

The contract fully implements the entrypoints of the FA2 standard according to [TZIP-12](https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-12/tzip-12.md). The other exchange-specific entrypoints are described in the doc.

## Code

{% embed url="<https://github.com/madfish-solutions/quipuswap-token2token-core/blob/master/contracts/main/Dex.ligo>" %}

## State-Changing Functions

### AddPair

{% code title="types.ligo" %}

```
type fa2_token_type     is
record [
  token_address           : address;
  token_id                : nat;
]

type token_type        is
| Fa12                    of address
| Fa2                     of fa2_token_type


type tokens_type        is 
[@layout:comb]
record [
  token_a_type            : token_type; (* token A standard *)
  token_b_type            : token_type; (* token B standard *)
]


type add_pair_params  is 
[@layout:comb]
record [
  pair                    : tokens_type; (* exchange pair info *)
  token_a_in              : nat; (* min amount of tokens A invested  *)
  token_b_in              : nat; (* min amount of tokens B invested *)
]
```

{% endcode %}

Setup the new exchange or relaunch the exchange after all the liquidity was drained. `amount_a_in` and `amount_b_in` of tokens must be approved. Initial liquidity should be non-zero. All the storage parameters are reset to default values. The sender receives shares equal to a minimum of `amount_a_in` and `amount_b_in`. Tokens types must be provided in ascending order.

| Parameter      | Type         | Description                               |
| -------------- | ------------ | ----------------------------------------- |
| token\_a\_type | tokens\_type | The type of the first token               |
| token\_b\_type | tokens\_type | The type of the second token              |
| token\_a\_in   | nat          | Amount of the first token to be invested  |
| token\_b\_in   | nat          | Amount of the second token to be invested |

### Swap

```
type swap_type          is
| A_to_b
| B_to_a

type swap_slice_type    is 
record [
  pair_id                 : nat;
  operation               : swap_type;
]

type swap_type          is 
[@layout:comb]
record [
  swaps                   : list(swap_slice_type);
  amount_in               : nat;
  min_amount_out          : nat;
  receiver                : address;
  deadline                : timestamp;
]
 
```

Swaps the token to another token. `a_to_b` type is used to exchange `token_a` to `token_b`. `b_to_a` performs the opposite swap from `token_b_address` to `token_a_address`. The `token_a` and `token_b` are the corresponding tokens of `pair_id` pool. The `amount_in` of the token will be charged from the user. If the received amount is smaller than `min_amount_out` then the transaction is reverted. Tokens types must be provided in ascending order. Deadlines should be in the future.

| Parameter        | Type                      | Description                                                                                                                          |
| ---------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| swaps            | list of swap\_slice\_type | Swaps to perform; each swap consist of `pair_id` of the pool and `swap_type` to be executed; all the exchanges should be sequential. |
| amount\_in       | nat                       | Amount of the token to swap                                                                                                          |
| min\_amount\_out | nat                       | The minimal amount of the token to receive                                                                                           |
| receiver         | address                   | Receiver's address                                                                                                                   |
| deadline         | timestamp                 | Time until the operation is valid                                                                                                    |

### Invest

```
type invest_type        is 
[@layout:comb]
record [
  pair_id                 : nat;
  shares                  : nat;
  token_a_in              : nat;
  token_b_in              : nat;
  deadline                : timestamp;
]
```

Adds more liquidity to the exchange. `token_a_in` and `token_b_in` must be approved. Initial liquidity should be non-zero. The sender spends `token_a_in` and `token_b_in` at most otherwise, the transaction fails. Tokens types must be provided in ascending order. Deadlines should be in the future.

| Parameter    | Type      | Description                              |
| ------------ | --------- | ---------------------------------------- |
| pair\_id     | nat       | Pair identifier                          |
| shares       | nat       | Amount of LP tokens to mint              |
| token\_a\_in | nat       | Max amount of the first token to invest  |
| token\_b\_in | nat       | Max amount of the second token to invest |
| deadline     | timestamp | Time until the operation is valid        |

### Divest

```
type divest_type        is 
[@layout:comb]
record [
  pair_id                 : nat;
  min_token_a_out         : nat;
  min_token_b_out         : nat;
  shares                  : nat;
  deadline                : timestamp;
]
```

Burns `shares` and sends tokens to the owner; operation is reverted if the amount of appropriate divested tokens is smaller than `min_token_a_out` or `min_token_b_out`. Tokens types must be provided in ascending order. Deadlines should be in the future.

| Parameter          | Type      | Description                                   |
| ------------------ | --------- | --------------------------------------------- |
| pair\_id           | nat       | Pair identifier                               |
| min\_token\_a\_out | nat       | Minimal amount of the first token to receive  |
| min\_token\_b\_out | nat       | Minimal amount of the second token to receive |
| shares             | nat       | The amount of the shares to burn              |
| deadline           | timestamp | Time until the operation is valid             |

### Close

```
type close_type        is unit
```

Is used after all the exchange calls to prevent reentrancy. It can only be called by the exchange itself.

## Read-Only Functions

### Get\_reserves

```
type reserves_type      is 
record [
  receiver                : contract(nat * nat);
  pair_id                 : nat;
]
```

Returns the amount of tokens reserves. No arguments are needed.


# Exceptions

In some cases, the contract's execution might fail. The current chapter describes the list of possible in-contract failures.

| Error                    | Description                                                                                                        |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| Dex/reentrancy           | It is prohibited to call the exchange until the previous operation is finished.                                    |
| Dex/function-not-set     | The code for the entrypoint doesn't exist in the bigmap. Should be unreachable.                                    |
| Dex/not-entered          | The contract can't be called until the previous method execution isn't finished.                                   |
| Dex/not-self             | The method should be called by the exchange contract only.                                                         |
| Dex/not-token            | The token doesn't implement the standard entrypoint.                                                               |
| Dex/not-close-entrypoint | The exchange contract doesn't have close entrypoint. Should be unreachable.                                        |
| Dex/not-launched         | The exchange for the pair isn't launched.                                                                          |
| Dex/no-liquidity         | Action can't be performed if there is no liquidity in the pool.                                                    |
| Dex/no-token-a-in        | The amount of invested token A can't be zero.                                                                      |
| Dex/no-token-b-in        | The amount of invested token B can't be zero.                                                                      |
| Dex/pair-exist           | The exchange can't be launched if it already exists.                                                               |
| Dex/wrong-route          | The exchange route isn't cohesive.                                                                                 |
| Dex/zero-amount-in       | Invest of zero tokens on one of the sides is not allowed.                                                          |
| Dex/insufficient-shares  | Not enough shares to burn.                                                                                         |
| Dex/dust-output          | One or all divested token amounts are zero.                                                                        |
| Dex/high-min-out         | The expected output is higher than the possible.                                                                   |
| Dex/wrong-pair-order     | The tokens should be provided in ascending order.                                                                  |
| Dex/empty-route          | The provided exchange route is empty.                                                                              |
| Dex/low-max-token-a-in   | The max amount of token A to deposit for the shares is insufficient.                                               |
| Dex/low-max-token-b-in   | The amount of token B to withdraw for the shares is too low.                                                       |
| Dex/action-outdated      | The operation isn't outdated.                                                                                      |
| Dex/wrong-reserves-state | After divest, some reserves and total shares aren't all zero or aren't all non-zero values. Should be unreachable. |
| Dex/low-supply           | The amount of divested shares is higher than the total supply. Should be unreachable.                              |


# QuipuSwap stable swap DEX

## About

Stable DEX, as a part of the growing QuipuSwap ecosystem, provides a platform for price-efficient and low-risk stablecoin or equal-price token trading. We intend to create a solution for the Tezos ecosystem akin to that Curve and Ellipsis have created for Ethereum and BSC, respectively.

{% embed url="<https://github.com/madfish-solutions/quipuswap-stable-core>" %}
Code of contracts
{% endembed %}

## Contracts overview

### Standalone

{% content-ref url="/pages/q94UFprVZKU0DGWTHJ4l" %}
[Standalone DEX](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex)
{% endcontent-ref %}

Is the all-in-one contract with a contract `admin` that allowed to add new DEX pools.&#x20;

{% content-ref url="/pages/2O8XuLgWJZW0HTvCJyid" %}
[Add new dex](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/add-new-dex)
{% endcontent-ref %}

Each pool stored in storage by `poolId` is an exchange between 2-4 tokens and has a corresponding LP token of FA2 standard with token ID = `poold`. Main DEX methods of each pool shown at

{% content-ref url="/pages/jVwwAm4e3a1fgbm6rFgP" %}
[DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods)
{% endcontent-ref %}

Also, the standalone includes [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module) inside it (Admin =/= Developer).

### Factory

{% content-ref url="/pages/Sb0vUsEdEtcIdxrqMbqF" %}
[Factory](/smart-contracts/quipuswap-stable-swap-dex/factory)
{% endcontent-ref %}

Allows use DaaS way to deploy new DEX pools for QUIPU fee and use own Stable Exchange with own params. For security reasons, each DEX pool is deployed as a separate contract.

{% content-ref url="/pages/w9gpnHIA7Wj5mJmIcCcV" %}
[Initialize new DEX flow](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow)
{% endcontent-ref %}

These deployed pools almost have the same logic as the standalone variant with a little difference - only one pool per contract. Each contract knows about factory, where located [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module).&#x20;

**`Developer`**, formally is the administrator of Factory. This address performs the initial setup of lambda methods

{% content-ref url="/pages/8Se1NJsiqg3vF85IYgos" %}
[Initial setup](/smart-contracts/quipuswap-stable-swap-dex/factory/initial-setup)
{% endcontent-ref %}

&#x20;and some additional setters

{% content-ref url="/pages/VVycbFQbvBJA7Yvo0xP4" %}
[Factory params](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/factory-management/factory-params)
{% endcontent-ref %}

### The main difference in implementations

In short, the difference is that

| Standalone pool                                                                             | Factory pool                                                                            |
| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| each pool has own `poolId`, as known as token ID of pool's corresponding FA2 typed LP token | each pool LP token is an FA2 typed with token Id `0` and an unique address              |
| only administrator allowed to add new pools                                                 | everyone could start a new pool when paid gas fees and some deploy fee in QUIPU tokens. |
| contract owns developer params                                                              | pool calls factory views for developer params                                           |

#### Developer key values stay in the developer's hands.

Developer represents person or group that create and improve code of Standalone or Factory contract. This address allows to claim fee rewards and manage some values. More info about main developer setter/storage module is shown here

{% content-ref url="/pages/7JDtxZWO96gtVLGz6i4C" %}
[Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module)
{% endcontent-ref %}

Additional values stored inside the implementation of specific contract - Factory or Standalone.


# Developer module

This module contains storage with developer address, developer fee rate and its compiled setter lambdas.

### Module contents

#### Storage

Inside [Standalone DEX](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex) and [Factory](/smart-contracts/quipuswap-stable-swap-dex/factory) contracts, storage contains the following structure:

```pascaligo
type main_storage_t   is [@layout:comb] record[
  //...
  dev_store             : dev_storage_t;
  //...
]

type storage_root     is [@layout:comb] record[
  //...
  storage               : main_storage_t;
  //...
]
```

This module expects the following structure and operates with the `dev_store` field. More details about module storage types are in section.

{% content-ref url="/pages/4CwdOCT6wvSV6vXLIZoH" %}
[Storage & action types](/smart-contracts/quipuswap-stable-swap-dex/developer-module/storage-and-action-types)
{% endcontent-ref %}

#### Setters

{% hint style="warning" %}
This entrypoints should be called only by `developer` address.&#x20;
{% endhint %}

All module fields have own setters. For calling this setters, used `call_dev` method.

{% code title="dev/methods.ligo" %}

```pascaligo
[@inline] function unwrap(
  const param           : option(_a);
  const error           : string)
                        : _a is
  case param of
  | Some(instance) -> instance
  | None -> failwith(error)
  end;

(* This methods called only by dev and modifies only `dev_storage` *)
[@inline] function call_dev(
  const p               : dev_action_t;
  var s                 : dev_storage_t)
                        : dev_storage_t is
  block {

    require(Tezos.sender = s.dev_address, Errors.not_developer);

    const idx : nat = case p of
    | Set_dev_address(_)  -> 0n
    | Set_dev_fee(_)      -> 1n
    end;

    const lambda_bytes : bytes = unwrap(s.dev_lambdas[idx], Errors.unknown_func);
    const func: dev_func_t = unwrap((Bytes.unpack(lambda_bytes) : option(dev_func_t)), Errors.wrong_use_function);
  } with func(p, s)
```

{% endcode %}

{% content-ref url="/pages/eA46ciGNfFQb8Yu8eg7H" %}
[Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints)
{% endcontent-ref %}


# Storage & action types

### Developer actions

Action type for module setters.

{% content-ref url="/pages/eA46ciGNfFQb8Yu8eg7H" %}
[Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints)
{% endcontent-ref %}

```pascaligo
type dev_action_t       is
| Set_dev_address         of address
| Set_dev_fee             of nat
```

### Developer storage

<table><thead><tr><th width="206.35180549489237">Field</th><th width="166" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>dev_address</td><td align="center"><code>address</code></td><td></td><td>Address of developer</td></tr><tr><td>dev_fee</td><td align="center"><code>nat</code></td><td>(decimal) multiplied by <code>fee_denominator</code> (1e10)</td><td>fee rate that goes to dev.</td></tr><tr><td>dev_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>Developer action lambdas</td></tr></tbody></table>

```pascaligo
type dev_storage_t      is [@layout:comb] record [
  dev_address             : address;
  dev_fee                 : nat;
  dev_lambdas             : big_map(nat, bytes);
]
```

#### Lambda type

Lambda is stored as `bytes`, packed from `dev_func_t`.

```pascaligo
type dev_func_t is (dev_action_t * dev_storage_t) -> dev_storage_t
```


# Developer setter entrypoints

This section describes setters of developer module.

#### Address

Sets developer address.

{% content-ref url="/pages/YXiHHkxJgX61CZsWLR8g" %}
[set\_dev\_address](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints/set_dev_address)
{% endcontent-ref %}

#### Fee rate

Sets developer fee rate.

{% content-ref url="/pages/ME48GVyRiBgFp0pNy9o5" %}
[set\_dev\_fee](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints/set_dev_fee)
{% endcontent-ref %}


# set\_dev\_address

Sets new developer address. Input value is `address`.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th>Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>address</code></td><td>Address of the new developer</td></tr></tbody></table>


# set\_dev\_fee

Sets developer fee rate. Input value is `nat`.

{% hint style="info" %}
Fee stored as float value multiplied by `fee_denominator` = $$10^{10}$$
{% endhint %}

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th>Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>nat</code></td><td>Developer fee value. This value is a percent from value (where <span class="math">10^{10} = 100\%</span>). Dev fee percent is less than <span class="math">50\%</span>.</td></tr></tbody></table>


# Standalone DEX

This all-in-one contract, managed by `admin`. Each deployed DEX is stored inside the current contract and has its own FA2 token. Access to a specific DEX, implemented by pool ID. This ID is an also LP token ID. Every token metadata is managed by any of the manager's addresses.

### Storage

Contract storage has a complicated structure all info about storage is collected on the page below.

{% content-ref url="/pages/TtvN4KVYD8lnC32cRE47" %}
[Storage and types overview](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/storage-and-types-overview)
{% endcontent-ref %}

### Core methods

Main methods of DEX, that are able to use by anyone. These methods include investing, swapping, and divesting. Also, there are additional methods for staking QUIPU tokens for earning additional rewards and claiming referral rewards.

{% content-ref url="/pages/jVwwAm4e3a1fgbm6rFgP" %}
[DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods)
{% endcontent-ref %}

### Developer-only methods

The developer section contains [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module) entrypoints and additional methods for claiming developer rewards.

{% hint style="warning" %}
These entrypoints should be called only by `developer` address.&#x20;
{% endhint %}

{% content-ref url="/pages/OOgbdccYFLb55qLGpGJ0" %}
[Developer methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/developer-methods)
{% endcontent-ref %}

### Admin methods

{% hint style="warning" %}
These entrypoints should be called only by `admin` address.&#x20;
{% endhint %}

The next section is about entrypoints for managing fees, "A" constant change, editing manager list, and changing an admin address.

{% content-ref url="/pages/tjIFtpRpiwljFf1SrU53" %}
[Admin methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods)
{% endcontent-ref %}

#### Initial setup of contract

These methods should be used **before** global usage of contract. Entrypoints set lambda-functions to its corresponding indexes inside related big maps.

{% content-ref url="/pages/Im047SfQhHVM3lqXvFvB" %}
[Initialization](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization)
{% endcontent-ref %}

#### Create a new DEX pool

Creating a new DEX pool in the standalone variant is an admin function. So only the admin can create a new pool. Admin should approve the needed amount of tokens before calling this method because call includes transfer selected tokens to contract.

{% content-ref url="/pages/2O8XuLgWJZW0HTvCJyid" %}
[Add new dex](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/add-new-dex)
{% endcontent-ref %}

### Examples hint

{% hint style="info" %}
All examples use LP token with `decimals` of $$18$$ ↔ `precision` constant as $$10^{18}$$ and 3 "abstract" tokens `TBC`, `TXZ`, `TEH` that have ratios $$4:2:1$$ respectively.
{% endhint %}


# Storage and types overview

Contract typings and storage

### Base types

```pascaligo
type token_id_t        is nat

type pool_id_t         is nat

type token_pool_idx_t  is nat

type fa12_token_t      is address

type fa2_token_t       is [@layout:comb] record[ 
    token_address        : address; 
    token_id             : token_id_t; 
]

type token_t           is 
| Fa12                   of fa12_token_t 
| Fa2                    of fa2_token_t

type tokens_map_t      is map(nat, token_t);
```

### Staker accumulator - accumulator of QUIPU staking rewards.

<table><thead><tr><th width="157.23880597014926">Field</th><th width="241.7580619284454" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>accumulator</td><td align="center"><code>map(token_pool_idx_t, nat)</code></td><td>For better accuracy, stored with multiplication by <span class="math">10^{10}</span>.</td><td>Mapping of token index and corresponding underlying accumulated balance of token</td></tr><tr><td>total_staked</td><td align="center"><code>nat</code></td><td></td><td>balance of staked QUIPU tokens to current pool</td></tr></tbody></table>

```pascaligo
type staker_accum_t     is [@layout:comb] record [
  accumulator             : map(token_pool_idx_t, nat);
  total_staked            : nat;
]
```

### Fee storage - fee rates record

<table><thead><tr><th width="206.35180549489237">Field</th><th width="150" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>lp</td><td align="center"><code>nat</code></td><td>Decimal value. Multiplied by <span class="math">10^{10}</span>.</td><td><p>Percent of fee goes to liquidity providers.</p><p>This fee stays in liquidity pool to increase LP token price.</p></td></tr><tr><td>stakers</td><td align="center"><code>nat</code></td><td>Decimal value. Multiplied by <span class="math">10^{10}</span>.</td><td>Percent of fee goes to QUIPU token stakers of pool. This fee goes to staking accumulator and spreads between users who staked QUIPU token to pool. If noone staked this fee part goes to liquidity pool as additional fee.</td></tr><tr><td>ref</td><td align="center"><code>nat</code></td><td>Decimal value. Multiplied by <span class="math">10^{10}</span>.</td><td>Percent of fee goes to referral of DEX call. This fee goes to referral address passed to DEX call. If referral not passed, fee goes to default referral.</td></tr></tbody></table>

```pascaligo
type fees_storage_t     is [@layout:comb] record [
  lp                      : nat;
  stakers                 : nat;
  ref                     : nat;
]
```

### Token information type - pool underlying token info

<table><thead><tr><th width="206.35180549489237">Field</th><th width="150" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>rate</td><td align="center"><code>nat</code></td><td>Calculates with pecisions. By default LP precision is 1e18. Rate is the value allowing to set custom exchange ratios between underlying tokens</td><td>Indicates how much LP token belongs to each underlying stablecoin</td></tr><tr><td>precision_multiplier</td><td align="center"><code>nat</code></td><td>By default LP precision is 1e18. Than <code>precision_multiplier</code> is <span class="math">10^{decimals_{LP} - decimals_{token}}</span></td><td>value that underlying token reserves are multiplied by in order to adjust their precision to LP decimal places</td></tr><tr><td>reserves</td><td align="center"><code>nat</code></td><td></td><td>balance of underlying token, locked in pool</td></tr></tbody></table>

```pascaligo
type token_info_t       is  [@layout:comb] record [
  rate                    : nat;
  precision_multiplier    : nat;
  reserves                : nat;
]
```

### Pool type - DEX pool storage

<table><thead><tr><th width="208.35180549489237">Field</th><th width="252" align="center">Type</th><th width="151">Hint</th><th>Description</th></tr></thead><tbody><tr><td>initial_A</td><td align="center"><code>nat</code></td><td>A constant stores as multiplied value. <span class="math"> A * n^{n-1} * 10^2</span>(10^2 is precision)</td><td>Start value of ramping A contant.</td></tr><tr><td>initial_A_time</td><td align="center"><code>timestamp</code></td><td>Timestamp in seconds</td><td>Time when ramping A constant was started.</td></tr><tr><td>future_A</td><td align="center"><code>nat</code></td><td>A constant stores as multiplied value. <span class="math"> A * n^{n-1} * 10^2</span>(10^2 is precision)</td><td>End value of ramping A contant.</td></tr><tr><td>future_A_time</td><td align="center"><code>timestamp</code></td><td>Timestamp in seconds</td><td>Time when ramping A constant will be finished</td></tr><tr><td>tokens_info</td><td align="center"><code>map(token_pool_idx_t, token_info_t)</code></td><td></td><td><a data-mention href="#token-information-type-pool-underlying-token-info">#token-information-type-pool-underlying-token-info</a></td></tr><tr><td>fee</td><td align="center"><code>fees_storage_t</code></td><td></td><td><a data-mention href="#fee-storage-fee-rates-record">#fee-storage-fee-rates-record</a></td></tr><tr><td>staker_accumulator</td><td align="center"><code>staker_accum_t</code></td><td></td><td><a data-mention href="#staker-accumulator-accumulator-of-quipu-staking-rewards.">#staker-accumulator-accumulator-of-quipu-staking-rewards.</a></td></tr><tr><td>total_supply</td><td align="center"><code>nat</code></td><td></td><td>Total supply of LP token.</td></tr></tbody></table>

```pascaligo
type pool_t             is [@layout:comb] record [
  initial_A               : nat;
  initial_A_time          : timestamp;
  future_A                : nat;
  future_A_time           : timestamp;
  tokens_info             : map(token_pool_idx_t, token_info_t);
  fee                     : fees_storage_t;
  staker_accumulator      : staker_accum_t;
  total_supply            : nat;
]
```

### Storage - main contract storage

<table><thead><tr><th width="185.35180549489237">Field</th><th width="254" align="center">Type</th><th width="233">Hint</th><th>Description</th></tr></thead><tbody><tr><td>admin</td><td align="center"><code>address</code></td><td></td><td>Administator of current contract</td></tr><tr><td>default_referral</td><td align="center"><code>address</code></td><td></td><td>Default referral address to apply fees</td></tr><tr><td>managers</td><td align="center"><code>set(address)</code></td><td>Manager could edit LP token metadata.</td><td>Set of managers addresses</td></tr><tr><td>pools_count</td><td align="center"><code>nat</code></td><td>Counter</td><td>Amount of pools created inside current contract.</td></tr><tr><td>tokens</td><td align="center"><code>big_map(pool_id_t, tokens_map_t)</code></td><td></td><td>Mapping of tokens, that exchanges inside created pool. </td></tr><tr><td>pool_to_id</td><td align="center"><code>big_map(bytes, nat)</code></td><td>Bytes - packed by <code>Bytes.pack(tokens)</code> where tokens is valid <code>tokens_map_t</code> (sorted tokens).</td><td>Mapping that allows finding pool id by packed bytes of <code>tokens_map_t</code></td></tr><tr><td>pools</td><td align="center"><code>big_map(pool_id_t, pool_t)</code></td><td></td><td>Mapping of pool to it's corresponding pool <a data-mention href="#pool-type-dex-pool-storage">#pool-type-dex-pool-storage</a></td></tr><tr><td>ledger</td><td align="center"><p><code>big_map(</code></p><p><code>(address * pool_id_t), nat)</code></p></td><td></td><td>Mapping of user's LP token balance related to pool</td></tr><tr><td>allowances</td><td align="center"><p><code>big_map(</code></p><p><code>(address * pool_id_t), allowances_data_t)</code></p></td><td></td><td>Storage of operators allowed to transfer LP tokens of user's behalf.</td></tr><tr><td>dev_rewards</td><td align="center"><code>big_map(token_t, nat)</code></td><td></td><td>Mapping of accrued developer rewards by each token.</td></tr><tr><td>referral_rewards</td><td align="center"><p><code>big_map(</code></p><p><code>(address * token_t), nat)</code></p></td><td></td><td>Mapping of accrued referral rewards by each user-token key.</td></tr><tr><td>stakers_balance</td><td align="center"><p><code>big_map(</code></p><p><code>(address * pool_id_t), staker_info_t)</code></p></td><td></td><td>Mapping of accrued staking rewards by each user-token key.</td></tr><tr><td>quipu_token</td><td align="center"><code>fa2_token_t</code></td><td></td><td>QUIPU token address and token ID</td></tr><tr><td>dev_store</td><td align="center"><code>dev_storage_t</code></td><td></td><td><a data-mention href="/smart-contracts/quipuswap-stable-swap-dex/developer-module/storage-and-action-types#developer-storage">Storage &amp; action types</a></td></tr></tbody></table>

```pascaligo
type storage_t          is [@layout:comb] record [
  (* Management *)
  admin                   : address;
  default_referral        : address;
  managers                : set(address);

  (* Pools data *)
  pools_count             : nat; (* total pools count *)
  tokens                  : big_map(pool_id_t, tokens_map_t); (* all the tokens list *)
  pool_to_id              : big_map(bytes, nat); (* all the tokens list *)
  pools                   : big_map(pool_id_t, pool_t); (* pool info per token id *)

  (* FA2 data *)
  ledger                  : big_map((address * pool_id_t), nat); (* account info per address *)
  allowances              : big_map((address * pool_id_t), allowances_data_t); (* account info per each lp provider *)

  (* Rewards and accumulators *)
  dev_rewards             : big_map(token_t, nat);
  referral_rewards        : big_map((address * token_t), nat);
  stakers_balance         : big_map((address * pool_id_t), staker_info_t);
  quipu_token             : fa2_token_t;
  (* dev storage params *)
  dev_store               : dev_storage_t;
]
```

### Full storage type - storage root

<table><thead><tr><th width="183.44565217391303">Field</th><th width="221" align="center">Type</th><th width="150">Hint</th><th>Description</th></tr></thead><tbody><tr><td>storage</td><td align="center"><code>storage_t</code></td><td><a data-mention href="#storage-main-contract-storage">#storage-main-contract-storage</a></td><td>Indicates how much LP token belongs to each underlying stablecoin</td></tr><tr><td>metadata</td><td align="center"><code>big_map(string, bytes)</code></td><td>TZIP-016</td><td>contract metadata by <a href="https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-16/tzip-16.md">TZIP-016</a></td></tr><tr><td>token_metadata</td><td align="center"><code>big_map(token_id_t, token_meta_info_t)</code></td><td>TZIP-016, TZIP-012</td><td>mapping each token metadata by <a href="https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-12/tzip-12.md">TZIP-012</a></td></tr><tr><td>admin_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>Administrative lambda-methods storage</td></tr><tr><td>dex_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>DEX stable swap protocol lambda-methods storage</td></tr><tr><td>token_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>FA2 lambda-methods storage</td></tr></tbody></table>

```pascaligo
type full_storage_t     is [@layout:comb] record [
  storage                 : storage_t; (* real dex storage_t *)
  (* Token Metadata *)
  metadata                : big_map(string, bytes); (* metadata storage_t according to TZIP-016 *)
  token_metadata          : big_map(token_id_t, token_meta_info_t);
  (* Contract lambdas storage *)
  admin_lambdas           : big_map(nat, bytes); (* map with admin-related functions code *)
  dex_lambdas             : big_map(nat, bytes); (* map with exchange-related functions code *)
  token_lambdas           : big_map(nat, bytes); (* map with token-related functions code *)
]
```


# Initialization

The initialization section includes documentation about entrypoints, that should be executed right **after deploy** and **before usage** of this contract.&#x20;

{% hint style="warning" %}
These contract methods are called only by `admin` of that contract.
{% endhint %}

### Admin lambdas

This entrypoint sets [Admin methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods) lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/ZsNsYr0MxLsxPcaBL0Mr" %}
[set\_admin\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_admin_function)
{% endcontent-ref %}

### Developer lambdas

This entrypoint sets [Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints) lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/aeLKEd14RgHwekgkTCuI" %}
[set\_dev\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_dev_function)
{% endcontent-ref %}

### DEX lambdas

This entrypoint sets [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods) lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/TAOgDZC5FXc9A0PmYkY1" %}
[set\_dex\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_dex_function)
{% endcontent-ref %}

### FA2 standard lambdas

This entrypoint sets FA2 interface lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/7tmKi8Wwuix7wrgNr2zq" %}
[set\_token\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_token_function)
{% endcontent-ref %}


# set\_admin\_function

Method for set admin functions.

There are 8 functions that belong to admin methods in the Standalone variant and 7 functions in the Factory variant (`add_pool` [Add new dex](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/add-new-dex) excluded from Factory variant).

```pascaligo
0n -> add_rem_managers
1n -> set_admin
2n -> claim_dev // called by developer address, check for admin address skipped
3n -> ramp_A
4n -> stop_ramp_A
5n -> set_fees
6n -> set_default_referral
7n -> add_pool // excluded in Factory implementation
```

### Input parameters type

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>func</td><td align="center"><code>bytes</code></td><td><p>Packed bytes from </p><p><code>type admin_func_t is (admin_action_t * storage_t) -> return_t</code></p></td></tr><tr><td>index</td><td align="center"><code>nat</code></td><td>Index of the passed method to be set to the lambdas big_map</td></tr></tbody></table>

```pascaligo
type admin_action_t     is
| Add_rem_managers        of set_man_param_t
| Set_admin               of address
| Claim_developer         of claim_by_token_param_t
| Ramp_A                  of ramp_a_param_t
| Stop_ramp_A             of nat
| Set_fees                of set_fee_param_t
| Set_default_referral    of address
#if !FACTORY // flag separates stanalone and factory implementations
| Add_pool                of init_param_t
#endif


type return_t           is list(operation) * storage_t
type admin_func_t       is (admin_action_t * storage_t) -> return_t

type set_lambda_func_t  is [@layout:comb] record [
  func                    : bytes;
  index                   : nat;
]
```

{% hint style="warning" %}
This contract method is called only by `admin` of that contract.
{% endhint %}


# set\_dev\_function

Method for set developer functions, from [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module).

There are 2 functions that belong to [Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints).

```pascaligo
0n -> set_dev_address
1n -> set_dev_fee
```

### Input parameters type

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>func</td><td align="center"><code>bytes</code></td><td><p>Packed bytes from </p><p><code>type dev_func_t is (dev_action_t * dev_storage_t) -> dev_storage_t</code></p></td></tr><tr><td>index</td><td align="center"><code>nat</code></td><td>Index of the passed method to be set to the <code>dev_lambdas</code> big_map</td></tr></tbody></table>

```pascaligo
type dev_action_t       is
| Set_dev_address         of address
| Set_dev_fee             of nat

type dev_storage_t      is [@layout:comb] record [
  dev_address             : address;
  dev_fee_f               : nat;
  dev_lambdas             : big_map(nat, bytes);
]

type dev_func_t         is (dev_action_t * dev_storage_t) -> dev_storage_t

type set_lambda_func_t  is [@layout:comb] record [
  func                    : bytes;
  index                   : nat;
]
```

{% hint style="warning" %}
This contract method are called only by `admin` of that contract.&#x20;

For the Factory contract `developer` is `admin.`
{% endhint %}


# set\_dex\_function

Method for set dex core functions.

There are 7 functions that belong to [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods).

```pascaligo
0n -> swap
1n -> invest_liquidity
2n -> divest_liquidity
3n -> divest_imbalanced
4n -> divest_one_coin
5n -> claim_ref
6n -> stake
```

### Input parameters type

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>func</td><td align="center"><code>bytes</code></td><td><p>Packed bytes from </p><p><code>type dex_func_t is (dex_action_t * storage_t) -> return_t</code></p></td></tr><tr><td>index</td><td align="center"><code>nat</code></td><td>Index of the passed method to be set to the lambdas big_map</td></tr></tbody></table>

```pascaligo
type dex_action_t       is
(* Base actions *)
| Swap                    of swap_param_t
| Invest                  of invest_param_t
| Divest                  of divest_param_t
(* Custom actions *)
| Divest_imbalanced       of divest_imb_param_t
| Divest_one_coin         of divest_one_c_param_t
| Claim_referral          of claim_by_token_param_t
| Stake                   of stake_action_t

type return_t           is list(operation) * storage_t
type dex_func_t         is (dex_action_t * storage_t) -> return_t

type set_lambda_func_t  is [@layout:comb] record [
  func                    : bytes;
  index                   : nat;
]
```

{% hint style="warning" %}
This contract method is called only by `admin` of that contract.
{% endhint %}


# set\_token\_function

Method for set FA2 interface functions.

There are 7 functions that belong to [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods).

```pascaligo
0n -> transfer_ep
1n -> get_balance_of
2n -> update_operators
3n -> update_token_metadata
4n -> total_supply_view
```

### Input parameters type

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>func</td><td align="center"><code>bytes</code></td><td><p>Packed bytes from </p><p><code>type token_func_t is (token_action_t * full_storage_t) -> full_return_t</code></p></td></tr><tr><td>index</td><td align="center"><code>nat</code></td><td>Index of the passed method to be set to the lambdas big_map</td></tr></tbody></table>

```pascaligo
type token_action_t     is
| Transfer                of transfer_param_t
| Balance_of              of bal_fa2_param_t
| Update_operators        of operator_param_t
| Update_metadata         of upd_meta_param_t
| Total_supply            of ts_v_param_t

type full_return_t      is list(operation) * full_storage_t
type token_func_t       is (token_action_t * full_storage_t) -> full_return_t

type set_lambda_func_t  is [@layout:comb] record [
  func                    : bytes;
  index                   : nat;
]
```

{% hint style="warning" %}
This contract method is called only by `admin` of that contract.
{% endhint %}


# Add new dex

This page describes creation of new DEX pool.&#x20;

{% hint style="warning" %}
These contract methods are called only by `admin` of that contract.
{% endhint %}

Creation of pool consist of some parameters for seeting up DEX config.

#### a\_constant

Constant A used for manipulating with swap function. As larger the value of A, as more the function tends to be constant sum invariant. This constant is stored inside the contact as  $$A\_{storage} = A \* n^{n-1}$$ where $$2 \le n \le 4$$ - number of DEX underlying tokens. You could read more about this constant at Curve [whitepaper](https://curve.fi/files/stableswap-paper.pdf) and an explanation of Curve formulas.

{% embed url="<https://miguelmota.com/blog/understanding-stableswap-curve>" %}
An explanation of Curve formulas
{% endembed %}

#### input\_tokens

This param is a set of FA12/FA2 tokens that would be traded on DEX. `Set` type in Tezos contract is the sorted list of unique values, so you must keep in mind that for setting up `tokens_info` and when calling DEX.

#### tokens\_info

Token Info contains initial data for [Storage and types overview](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/storage-and-types-overview#token-information-type-pool-underlying-token-info).&#x20;

{% content-ref url="/pages/n3lsAcESil7i0lTtyJzr" %}
[add\_pool](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/add-new-dex/add_pool)
{% endcontent-ref %}

### Token info setting

When you want to initialise pool, you should setup initial `reserves`, `rate` and `precision_multiplier` in correct way:

> Let 4 `TBC` = 2 `TXZ` = 1 `TEH` (from example)

Then calculate $$LCM$$ of these ratios $$= 4$$

Token info for `TBC`

> `precision_multiplier` - $$10^{decimal\_{LP} - decimal\_{TBC}}$$
>
> `rate` - $$10^{decimal\_{LP}} \* 10^{decimal\_{LP} - decimal\_{TBC}} \* (ratio\_{TBC}/LCM)$$
>
> `reserves` - $$N \* 10^{decimal\_{TBC}} \* ratio\_{TBC}$$

Token info for `TXZ`

> `precision_multiplier` - $$10^{decimal\_{LP} - decimal\_{TXZ}}$$
>
> `rate` - $$10^{decimal\_{LP}} \* 10^{decimal\_{LP} - decimal\_{TXZ}} \* (ratio\_{TXZ}/LCM)$$
>
> `reserves` - $$N \* 10^{decimal\_{TXZ}} \* ratio\_{TXZ}$$

Token info for `TEH`

> `precision_multiplier` - $$10^{decimal\_{LP} - decimal\_{TEH}}$$
>
> `rate` - $$10^{decimal\_{LP}} \* 10^{decimal\_{LP} - decimal\_{TEH}} \* (ratio\_{TEH}/LCM)$$
>
> `reserves` - $$N \* 10^{decimal\_{TEH}} \* ratio\_{TEH}$$

Then you should receive $$LPT = 10^{decimal\_{LP}} \* LCM \* tokensCount$$ LP tokens.

Details of how to calculate values are in this table. (You can copy and play with this sheet)

{% embed url="<https://docs.google.com/spreadsheets/d/16sfuK6o8mWxOtG4pagxvRiUoswmA4SUO4aFzDa8yTD8/edit?usp=sharing>" %}
Stable exchange with switching of amount of tokens
{% endembed %}


# add\_pool

This entrypoint allows `admin` creating a new DEX pool.

{% hint style="info" %}
Underlying tokens should be approved (updated operators) before calling this method.
{% endhint %}

### Call parameters

<table><thead><tr><th width="158">Field</th><th width="240" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>a_constant</td><td align="center"><code>nat</code></td><td>"A" constant</td></tr><tr><td>input_tokens</td><td align="center"><code>set(token_t)</code></td><td>set of tokens inside the future pool (from 2 to 4 entries)</td></tr><tr><td>tokens_info</td><td align="center"><code>map(token_pool_idx_t, token_info_t)</code></td><td>map of rates config and amount of initial pool reserves </td></tr></tbody></table>

```pascaligo
type init_param_t       is [@layout:comb] record [
  a_constant              : nat;
  input_tokens            : set(token_t);
  tokens_info             : map(token_pool_idx_t, token_info_t);
]
```

{% hint style="warning" %}
This contract method is called only by `admin` of that contract.
{% endhint %}


# DEX methods

The core entrypoints

### Investing

Any user could invest their own liquidity to contract and receive Liquidity Pool Token (LPT). LPT allows earning interest from [#swapping](#swapping "mention")and imbalanced invests/divests.&#x20;

#### Balanced invest

If user performs investment in corresponding ratios (example from [Standalone DEX](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex#examples-hint) \[4 `TBC`; 2 `TXZ`; 1 `TEH`] is balanced input), it is expected to no additional fees are charged.

#### Imbalanced invest

If there is any LPT already exists, and invest is imbalanced (example from [Standalone DEX](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex#examples-hint) \[1 `TBC`; 2 `TXZ`; 1 `TEH`] and \[1 `TXZ`] and \[8 `TXZ`; 4 `TEH`] is all imbalanced inputs) the additional fee charged for balancing pool reserves.

More info about invest entrypoint written out on the corresponding page.

{% content-ref url="/pages/9Js3mqY7emh7MMIEJ6Z5" %}
[invest](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/invest)
{% endcontent-ref %}

### Swapping&#x20;

The main idea of DEX is to swap between different liquidity entries. This contract used swap math, which tried to keep math calculations as close as possible to [Curve](https://curve.fi/) math. Each swap has a 0.05% fee that goes to liquidity providers (this part of the reward stays in liquidity pool), QUIPU pool stakers (if no one had staked yet, this part of the fee goes to liquidity providers), referral (if not provided goes to default referral address), and to the developer.

{% content-ref url="/pages/zT4uusC5vZtL4YUhhY5z" %}
[swap](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/swap)
{% endcontent-ref %}

### Divesting

The liquidity provider could take back his liquidity by performing divest operation. The provider could choose a more convenient divest method from 3 variants: balanced/imbalanced/in one coin. Info about the difference of variants described at Divesting page.

{% content-ref url="/pages/Og2NdUIEy4FqE5Ku9xMy" %}
[Divesting](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/divesting)
{% endcontent-ref %}

### Additional interest

Participators of  DEX pools are allowed to earn additional rewards as referrals or by staking QUIPU tokens. For more information about earning rewards in this way, follow the page under this text.

{% content-ref url="/pages/U8C6aXrITct5gHCRWMsA" %}
[DEX rewards](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/dex-rewards)
{% endcontent-ref %}


# invest

This entrypoint is designed to add liquidity to a specific DEX pool.

This method includes a balanced and imbalanced ways of investing.

### Call parameters

<table><thead><tr><th width="158">Field</th><th width="240" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>nat</code></td><td>pool identifier</td></tr><tr><td>shares</td><td align="center"><code>nat</code></td><td>the minimal amount of shares to receive</td></tr><tr><td>in_amounts</td><td align="center"><code>map(token_pool_idx_t, nat)</code></td><td>map of token amounts to be invested</td></tr><tr><td>deadline</td><td align="center"><code>timestamp</code></td><td>dealine of current operation</td></tr><tr><td>receiver</td><td align="center"><code>option(address)</code></td><td>optional, address of the receiver of the LP tokens. If not provided the <code>sender</code> address will be used.</td></tr><tr><td>referral</td><td align="center"><code>option(address)</code></td><td>optional, address of the referral of the current operation. If not provided the <code>default_referral</code> address will be used.</td></tr></tbody></table>

```pascaligo
type invest_param_t     is [@layout:comb] record [
  pool_id                 : nat; 
  shares                  : nat; 
  in_amounts              : map(token_pool_idx_t, nat); 
  deadline                : timestamp; 
  receiver                : option(address); 
  referral                : option(address);
]
```


# swap

This entrypoint is designed to swap tokens by a specific DEX.

### Call parameters

<table><thead><tr><th width="185">Field</th><th width="197" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>nat</code></td><td>pool identifier.</td></tr><tr><td>idx_from</td><td align="center"><code>token_pool_idx_t</code></td><td>index of input token.</td></tr><tr><td>idx_to</td><td align="center"><code>token_pool_idx_t</code></td><td>index of output token.</td></tr><tr><td>amount</td><td align="center"><code>nat</code></td><td>amount of input token.</td></tr><tr><td>min_amount_out</td><td align="center"><code>nat</code></td><td>minimal amount of output token expected to receive.</td></tr><tr><td>deadline</td><td align="center"><code>timestamp</code></td><td>deadline of current operation.</td></tr><tr><td>receiver</td><td align="center"><code>option(address)</code></td><td>optional, address of the receiver of the LP tokens. If not provided the <code>sender</code> address will be used.</td></tr><tr><td>referral</td><td align="center"><code>option(address)</code></td><td>optional, address of the referral of the current operation. If not provided the <code>default_referral</code> address will be used.</td></tr></tbody></table>

```pascaligo
type swap_param_t       is [@layout:comb] record [
  pool_id                 : nat; 
  idx_from                : token_pool_idx_t;
  idx_to                  : token_pool_idx_t;
  amount                  : nat;
  min_amount_out          : nat;
  deadline                : timestamp; 
  receiver                : option(address); 
  referral                : option(address);
]
```


# Divesting

Withdrawal actions contain 3 entrypoints that allow the user to withdraw underlying tokens by burning liquidity tokens.

* Balanced divest - classic removing liquidity without any additional fees.

{% content-ref url="/pages/XGcgKkml4rv5e3SUifDB" %}
[divest](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/divesting/divest)
{% endcontent-ref %}

* Imbalanced divest - allows to withdraw specific amount of underlying token(-s).

{% content-ref url="/pages/ccqshEZ7cy1QKGRCIJA4" %}
[divest\_imbalanced](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/divesting/divest_imbalanced)
{% endcontent-ref %}

* Divest in one coin - allows to withdraw in one of underlying token by burning specific amount of shares.

{% content-ref url="/pages/K5YrA56Cv3l9vPl30yix" %}
[divest\_one\_coin](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/divesting/divest_one_coin)
{% endcontent-ref %}

### Divest imbalance vs divest one

If you try to divest in imbalanced method you should pass **required** amount(-s) of output token(-s) and **maximum** of LP token (shares) to be burnt.

When you try to divest in one coin you should pass amount of shares to be burnt and **minimal amount** of token that you want to receive.

{% hint style="danger" %}
All of sent shares would be burnt when divest in one coin. Even if shares value greater than avaliable reserves of token.
{% endhint %}

In each way you would pay some fees to pool for imbalanced divest.

If you divest in balanced way, you wouldn’t pay any fees.


# divest

This entrypoint is designed to remove liquidity from a specific DEX pool according to current exchange rate.

### Call parameters

<table><thead><tr><th width="192">Field</th><th width="245" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>nat</code></td><td>pool identifier.</td></tr><tr><td>min_amounts_out</td><td align="center"><code>map(token_pool_idx_t, nat)</code></td><td>min amount of tokens to be received. NOTE: must be provided <strong>all</strong> indexes of tokens</td></tr><tr><td>shares</td><td align="center"><code>nat</code></td><td>amount of LP token to be burn.</td></tr><tr><td>deadline</td><td align="center"><code>timestamp</code></td><td>dealine of current operation.</td></tr><tr><td>receiver</td><td align="center"><code>option(address)</code></td><td>optional, address of the receiver of the LP tokens. If not provided the <code>sender</code> address will be used.</td></tr></tbody></table>

```pascaligo
type divest_param_t     is [@layout:comb] record [
  pool_id                 : nat;
  min_amounts_out         : map(token_pool_idx_t, nat);
  shares                  : nat; 
  deadline                : timestamp; 
  receiver                : option(address); 
]
```


# divest\_imbalanced

This entrypoint is designed to remove liquidity to receive specific underlying assets from the DEX pool.

### Call parameters

<table><thead><tr><th width="185">Field</th><th width="243" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>nat</code></td><td>pool identifier.</td></tr><tr><td>amounts_out</td><td align="center"><code>map(token_pool_idx_t, nat)</code></td><td>amount of tokens to be received. NOTE: must be provided <strong>at least one</strong> of indexes of tokens</td></tr><tr><td>max_shares</td><td align="center"><code>nat</code></td><td>maximum amount of LP tokens to be burnt.</td></tr><tr><td>deadline</td><td align="center"><code>timestamp</code></td><td>dealine of current operation.</td></tr><tr><td>receiver</td><td align="center"><code>option(address)</code></td><td>optional, address of the receiver of the LP tokens. If not provided the <code>sender</code> address will be used.</td></tr><tr><td>referral</td><td align="center"><code>option(address)</code></td><td>optional, address of the referral of the current operation. If not provided the <code>default_referral</code> address will be used.</td></tr></tbody></table>

```pascaligo
type divest_imb_param_t is [@layout:comb] record [
  pool_id                 : nat;
  amounts_out             : map(token_pool_idx_t, nat);
  max_shares              : nat; 
  deadline                : timestamp; 
  receiver                : option(address); 
  referral                : option(address);
]
```


# divest\_one\_coin

This entrypoint is designed to remove liquidity from a specific DEX pool in one underlying token.

### Call parameters

<table><thead><tr><th width="185">Field</th><th width="243" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>nat</code></td><td>pool identifier.</td></tr><tr><td>shares</td><td align="center"><code>nat</code></td><td>amount of LP tokens to be burnt.</td></tr><tr><td>token_index</td><td align="center"><code>token_pool_idx_t</code></td><td>index of token to be received.</td></tr><tr><td>min_amount_out</td><td align="center"><code>nat</code></td><td>amount of token to be received.</td></tr><tr><td>deadline</td><td align="center"><code>timestamp</code></td><td>dealine of current operation.</td></tr><tr><td>receiver</td><td align="center"><code>option(address)</code></td><td>optional, address of the receiver of the LP tokens. If not provided the <code>sender</code> address will be used.</td></tr><tr><td>referral</td><td align="center"><code>option(address)</code></td><td>optional, address of the referral of the current operation. If not provided the <code>default_referral</code> address will be used.</td></tr></tbody></table>

```pascaligo
type divest_one_c_param_t is [@layout:comb] record [
  pool_id                 : nat;
  shares                  : nat;
  token_index             : token_pool_idx_t;
  min_amount_out          : nat;
  deadline                : timestamp; 
  receiver                : option(address); 
  referral                : option(address);
]
```

{% hint style="danger" %}
The parameter `shares` provided to call, which represents the amount LP tokens would be burnt **in full**. So, if you want to burn more LP tokens **by value** than available reserves of the selected underlying token then you could **lose some of your liquidity**.
{% endhint %}


# DEX rewards

This section is about ways to earn additional rewards of pool usage.

## Referral

This rewards accured from passing referral addres to optional `referral` field when calling most of [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods). Referral can claim part or all of its rewards by calling `claim_referral`.

{% content-ref url="/pages/E6EfkK4K9U8lgRfJ7xol" %}
[claim\_referral](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/dex-rewards/claim_referral)
{% endcontent-ref %}

## Stake QUIPU token

Any user that has QUIPU tokens can stake them into liquidity pool to earn additional rewards. Staker rewards spreads between all of pool stakers proportionally to stake amount and time.&#x20;

{% content-ref url="/pages/d75y2Egrikn4e84YvVYV" %}
[stake](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods/dex-rewards/stake)
{% endcontent-ref %}


# claim\_referral

This entrypoint is designed to withdraw some of the collected referral rewards by the selected token.

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>token</td><td align="center"><code>token_t</code></td><td><code>FA2/FA1.2</code> token to claim.</td></tr><tr><td>amount</td><td align="center"><code>nat</code></td><td>amount of tokens to claim.</td></tr></tbody></table>

```pascaligo
type claim_by_token_param_t is [@layout:comb] record [
  token                   : token_t;
  amount                  : nat;
]
```


# stake

This entrypoint is designed to stake or unstake QUIPU tokens to a specific DEX pool.

{% hint style="info" %}
This call payoff staking rewards in all accrued tokens automatically.

Calling this method with `amount = 0n` and any path (`Add/Remove`) triggers payoff without transfer QUIPU tokens.&#x20;
{% endhint %}

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>pool_id_t</code></td><td>pool identifier.</td></tr><tr><td>amount</td><td align="center"><code>nat</code></td><td>amount of QUIPU tokens to stake or unstake.</td></tr></tbody></table>

```pascaligo
type stake_param_t      is [@layout:comb] record [
  pool_id                 : pool_id_t;
  amount                  : nat;

type stake_action_t     is
| Add of stake_param_t
| Remove of stake_param_t
```


# Developer methods

Manage developer fee, address and claim developer rewards

{% hint style="warning" %}
These entrypoints should be called only by `developer` address.&#x20;
{% endhint %}

### Manage developer info

Managing of developer info preforms by [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module). More info about usage of setting developer config params is provided on the page below.

{% content-ref url="/pages/eA46ciGNfFQb8Yu8eg7H" %}
[Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints)
{% endcontent-ref %}

### Claim rewards

Develper can claim part (or all) collected rewards by providing FA12/FA2 token and amount, that needed to receive. For this action is used entrypoint `claim_developer`.&#x20;

{% content-ref url="/pages/k45UEmSLmhDclXFsqRM6" %}
[claim\_developer](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/developer-methods/claim_developer)
{% endcontent-ref %}


# claim\_developer

{% hint style="warning" %}
This entrypoint should be called only by `developer` address.&#x20;
{% endhint %}

This entrypoint is designed to withdraw some of the collected referral rewards by the selected token.

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>token</td><td align="center"><code>token_t</code></td><td><code>FA2/FA1.2</code> token to claim.</td></tr><tr><td>amount</td><td align="center"><code>nat</code></td><td>amount of tokens to claim.</td></tr></tbody></table>

```pascaligo
type claim_by_token_param_t is [@layout:comb] record [
  token                   : token_t;
  amount                  : nat;
]
```


# Admin methods

{% hint style="warning" %}
These entrypoints should be called only by `admin` address.
{% endhint %}

Section is about administrative management. Admin could change managers, self, update fee rates and manage "A" constant (manipulate flattness of swap function).

### Change admin address

Method allows admin to hand over its rights to another address.

{% content-ref url="/pages/tTwuQvuhXnskZGjvegTR" %}
[set\_admin](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods/set_admin)
{% endcontent-ref %}

### Update contract fee rates

Entrypoint designed to update all fee rates except developer fee.

{% content-ref url="/pages/yRxICpxkC15Sdtq2nIkj" %}
[set\_fees](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods/set_fees)
{% endcontent-ref %}

### Add or remove token metadata managers

Method for add/remove manager addresses to manage LP token metadata.

{% content-ref url="/pages/EE3ev2mJJYnD9cI5c1Ci" %}
[add\_rem\_managers](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods/add_rem_managers)
{% endcontent-ref %}

### Manipulate DEX pool "A" constant

Method to set new "A" constant. Changing performed distributed over time from old "A" to new "A".

{% content-ref url="/pages/MAyrLpNbOEYj7a6UQFYV" %}
[ramp\_A](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods/ramp_a)
{% endcontent-ref %}

Method to stop changing "A" constant. The new "A" after stop would be specific "A" that counted at time of stopping (from ramping).

{% content-ref url="/pages/dSb35XByy2jCPKEu8NIA" %}
[stop\_ramp\_A](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods/stop_ramp_a)
{% endcontent-ref %}


# add\_rem\_managers

{% hint style="warning" %}
This entrypoint should be called only by `admin` address.
{% endhint %}

This entrypoint is designed to add or remove manager address.&#x20;

**Manager** - `address`, allowed to change metadata of any LP token.

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>add</td><td align="center"><code>bool</code></td><td><code>True</code> to add or <code>False</code> to remove candidate.</td></tr><tr><td>candidate</td><td align="center"><code>address</code></td><td>address of the candidate manager.</td></tr></tbody></table>

```pascaligo
type set_man_param_t    is [@layout:comb] record [
  add                     : bool;
  candidate               : address;
]
```


# ramp\_A

{% hint style="warning" %}
This entrypoint should be called only by `admin` address.
{% endhint %}

This entrypoint is designed to ramping the "A" constant, allowing to change "flattiness" of swap function.&#x20;

### How to set `A` constant?

`A` constant set to contract in precalculated invariant value as

$$A\_{storage} = A \* n^{n-1}$$

so, if you want to set `A` correctly you should keep it in mind.

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>pool_id_t</code></td><td>pool identifier.</td></tr><tr><td>future_A</td><td align="center"><code>nat</code></td><td>the target value of "A" constant.</td></tr><tr><td>future_time</td><td align="center"><code>timestamp</code></td><td>timestamp when ramping should be finished.</td></tr></tbody></table>

```pascaligo
type ramp_a_param_t     is [@layout:comb] record [
  pool_id                 : nat; 
  future_A                : nat;
  future_time             : timestamp;
]
```


# set\_admin

{% hint style="warning" %}
This entrypoint should be called only by `admin` address.
{% endhint %}

This entrypoint is designed to change the administrator address.&#x20;

Call param type is `address` - the new administrator address.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>address</code></td><td>the new admin address.</td></tr></tbody></table>


# set\_fees

{% hint style="warning" %}
This entrypoint should be called only by `admin` address.
{% endhint %}

This entrypoint is designed to update fee rates.

More info about fee storage and precisions, please, read [Storage and types overview](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/storage-and-types-overview#fee-storage-fee-rates-record) section.

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="190" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>pool_id</td><td align="center"><code>pool_id_t</code></td><td>pool identifier.</td></tr><tr><td>fee</td><td align="center"><code>fees_storage_t</code></td><td>contains fee rates, percent multiplied by <span class="math">10^{10}</span>, for liquidity providers, QUIPU token stakers, and for referral.</td></tr></tbody></table>

```pascaligo
type fees_storage_t     is [@layout:comb] record [
  lp                      : nat; 
  stakers                 : nat;
  ref                     : nat;
]

type set_fee_param_t    is [@layout:comb] record [
  pool_id                 : pool_id_t;
  fee                     : fees_storage_t;
]
```


# stop\_ramp\_A

{% hint style="warning" %}
This entrypoint should be called only by `admin` address.
{% endhint %}

This entrypoint is designed to stop ramping the "A" constant, when ramping in progress.

The new value of "A" fixed at time when stop is called.&#x20;

Call param type is `nat` - pool identifier.

### How to set `A` constant?

`A` constant set to contract in precalculated invariant value as

$$A\_{storage} = A \* n^{n-1}$$

so, if you want to set `A` correctly you should keep it in mind.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="190" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>pool_id_t</code></td><td>pool identifier.</td></tr></tbody></table>


# Factory

Factory is the implementation of DEX-as-a-service way to use DEX pool. Factory is used for deploying new DEX pools as separate contracts for some fee in QUIPU tokens. Also factory contract store and manage developer config from [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module). Also `developer` represents **admin** of factory contract.

### Storage

Factory storage contains init lambda, DEX contract lambdas, configuration of deploy price and burn rate, whitelist, and mapping of deployed pools.

{% content-ref url="/pages/cc9PUoaCACLib0UoIvDb" %}
[Storage and types overview](/smart-contracts/quipuswap-stable-swap-dex/factory/storage-and-types-overview)
{% endcontent-ref %}

### Initialization of factory

Factory should store many methods, so some of that stored in lambdas inside storage. These lambdas should be set **before** usage of the contract.&#x20;

{% hint style="warning" %}
This section called only by `developer` address.
{% endhint %}

{% content-ref url="/pages/8Se1NJsiqg3vF85IYgos" %}
[Initial setup](/smart-contracts/quipuswap-stable-swap-dex/factory/initial-setup)
{% endcontent-ref %}

### Call deploy of DEX

Initialization of new DEX separated into 2 stages because of gas transaction limits.&#x20;

The first stage deploys the contract and all lambdas except `dex_lambdas` (the heaviest lambdas by size) and charges QUIPU tokens but the contract has not started yet (frozen).&#x20;

The second stage should be called by caller address of the first stage and performs set of DEX lambdas to deployed DEX, unfreezes the contract, and call invest (as initial invest) of underlying tokens.

{% content-ref url="/pages/w9gpnHIA7Wj5mJmIcCcV" %}
[Initialize new DEX flow](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow)
{% endcontent-ref %}

### Deployed DEX

The link below describes the usage of deployed DEX contract and its storage.

{% content-ref url="/pages/B6Ce4Q1RCPeETBZL598h" %}
[Deployed from factory DEX](/smart-contracts/quipuswap-stable-swap-dex/factory/deployed-from-factory-dex)
{% endcontent-ref %}

### Developer-only (admin) methods

As a developer, you could manage the dev fee rate, set the deploy price, and its burn percent. Also, the developer could add and remove addresses to the whitelist (for deploying new pools without charging QUIPU).

{% content-ref url="/pages/gh2lVW1PZHAsc2lmHWIK" %}
[Developer methods](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods)
{% endcontent-ref %}


# Storage and types overview

### Base types

```pascaligo
type token_id_t        is nat

type pool_id_t         is nat

type token_pool_idx_t  is nat

type fa12_token_t      is address

type fa2_token_t       is [@layout:comb] record[ 
    token_address        : address; 
    token_id             : token_id_t; 
]

type token_t           is 
| Fa12                   of fa12_token_t 
| Fa2                    of fa2_token_t

type tokens_map_t      is map(nat, token_t);
```

### Storage - main contract storage

<table><thead><tr><th width="186.35180549489237">Field</th><th width="174" align="center">Type</th><th width="233">Hint</th><th>Description</th></tr></thead><tbody><tr><td>dev_store</td><td align="center"><code>dev_storage_t</code></td><td></td><td><a data-mention href="/smart-contracts/quipuswap-stable-swap-dex/developer-module/storage-and-action-types#developer-storage">Storage &amp; action types</a></td></tr><tr><td>init_price</td><td align="center"><code>nat</code></td><td></td><td>Amount of QUIPU tokens to be charged when deploy of DEX called.</td></tr><tr><td>burn_rate</td><td align="center"><code>nat</code></td><td>Decimal value. multiplied by <span class="math">10^6</span></td><td>Persent of QUIPU charges to be sent to zero address. </td></tr><tr><td>pools_count</td><td align="center"><code>nat</code></td><td>Counter</td><td>Amount of pools created by current contract.</td></tr><tr><td>pool_to_address</td><td align="center"><code>big_map(bytes, address)</code></td><td>Bytes - packed by <code>Bytes.pack(key)</code> where key is <code>record[ tokens=tokens; deployer=deployer]</code>  where tokens is valid <code>tokens_map_t</code> (sorted tokens) and deployer is address of user that deployed DEX contract.</td><td>Mapping that allows finding pool address by packed bytes of record with fields <code>tokens</code> of <code>tokens_map_t</code> type and <code>deployer</code> of <code>address</code>.</td></tr><tr><td>quipu_token</td><td align="center"><code>fa2_token_t</code></td><td></td><td>QUIPU token address and token ID</td></tr><tr><td>quipu_rewards</td><td align="center"><code>nat</code></td><td></td><td>Collected QUIPU tokens from deploy (without sent to zero address).</td></tr><tr><td>whitelist</td><td align="center"><code>set(address)</code></td><td></td><td>set of addresses that allowed to deploy without QUIPU charges.</td></tr></tbody></table>

```pascaligo
type inner_store_t      is [@layout:comb] record[
  dev_store               : dev_storage_t;
  init_price              : nat; (* Pool creation price in QUIPU token *)
  burn_rate               : nat; (* Percent of QUIPU tokens to be burned *)
  pools_count             : nat;
  pool_to_address         : big_map(bytes, address);
  quipu_token             : fa2_token_t;
  quipu_rewards           : nat;
  whitelist               : set(address);
]
```

### Full storage type - storage root

<table><thead><tr><th width="183.44565217391303">Field</th><th width="170" align="center">Type</th><th width="150">Hint</th><th>Description</th></tr></thead><tbody><tr><td>storage</td><td align="center"><code>inner_store_t</code></td><td><a data-mention href="#storage-main-contract-storage">#storage-main-contract-storage</a></td><td>Main configuration and contract values of factory</td></tr><tr><td>admin_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>Administrative lambda-methods storage</td></tr><tr><td>dex_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>DEX stable swap protocol lambda-methods storage</td></tr><tr><td>token_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>FA2 lambda-methods storage</td></tr><tr><td>init_func</td><td align="center"><code>option(bytes)</code></td><td></td><td>lambda function for deploying new DEX</td></tr></tbody></table>

```pascaligo
type full_storage_t     is [@layout:comb] record [
  storage                 : inner_store_t;
  admin_lambdas           : big_map(nat, bytes); (* map with admin-related functions code *)
  dex_lambdas             : big_map(nat, bytes); (* map with exchange-related functions code *)
  token_lambdas           : big_map(nat, bytes); (* map with token-related functions code *)
  init_func               : option(bytes); (* lambda function for deploying new DEX *)
]
```


# Initial setup

{% hint style="warning" %}
This section called only by `developer` address.
{% endhint %}

### DEX deploy function lambda

{% content-ref url="/pages/aH5mQCZX71gGaHz0vPMo" %}
[set\_init\_function](/smart-contracts/quipuswap-stable-swap-dex/factory/initial-setup/set_init_function)
{% endcontent-ref %}

### Developer lambdas

This entrypoint sets [Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints) lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/aeLKEd14RgHwekgkTCuI" %}
[set\_dev\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_dev_function)
{% endcontent-ref %}

### Pre-compiled DEX lambdas

These entrypoints are designed for setting lambdas that will be copied and used in deployed DEX pool contracts.

{% content-ref url="/pages/TbRmEChMqbJxHUQAmoBc" %}
[DEX compiled codebase setup](/smart-contracts/quipuswap-stable-swap-dex/factory/initial-setup/dex-compiled-codebase-setup)
{% endcontent-ref %}


# set\_init\_function

Method for set DEX contract deployer function lambda.

Deployer function deploys new DEX contract to the blockchain with copied admin and token lambdas and charges deploy fee in QUIPU tokens. Part of fees stays inside contact reserves (`quipu_rewards`) and the other part goes to "burn address" - hardcoded zero-address to burn QUIPU tokens.

Input param type is `bytes`.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="190" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>bytes</code></td><td>packed bytes from <code>type init_func_t is (pool_init_param_t * full_storage_t) -> fact_return_t</code></td></tr></tbody></table>

```pascaligo
type pool_init_param_t  is [@layout:comb] record [
  a_constant              : nat;
  input_tokens            : set(token_t);
  tokens_info             : map(token_pool_idx_t, token_prec_info_t);
  default_referral        : address;
  managers                : set(address);
  metadata                : big_map(string, bytes);
  token_metadata          : big_map(token_id_t, token_meta_info_t);
]

type fact_return_t      is list(operation) * full_storage_t

type init_func_t        is (pool_init_param_t * full_storage_t) -> fact_return_t
```

{% hint style="warning" %}
This contract method is called only by `developer` of that contract.
{% endhint %}


# DEX compiled codebase setup

{% hint style="warning" %}
This contract method are called only by `developer` of Factory.
{% endhint %}

### Admin lambdas

This entrypoint sets [Admin methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods) lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/ZsNsYr0MxLsxPcaBL0Mr" %}
[set\_admin\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_admin_function)
{% endcontent-ref %}

### DEX lambdas

This entrypoint sets [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods) lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/TAOgDZC5FXc9A0PmYkY1" %}
[set\_dex\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_dex_function)
{% endcontent-ref %}

### FA2 standard lambdas

This entrypoint sets FA2 interface lambda-functions to contract storage by function ID and function-packed bytes. &#x20;

{% content-ref url="/pages/7tmKi8Wwuix7wrgNr2zq" %}
[set\_token\_function](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/initialization/set_token_function)
{% endcontent-ref %}


# Initialize new DEX flow

Deploy and initialization of DEX pool from factory performs in 2 steps. This is required because of the complexity of the contract itself and the size of stored lambda functions in it, so one-operation deployment exceeds gas limits.

### Step 1

{% hint style="warning" %}
QUIPU token should be approved (updated operators) before calling this method.
{% endhint %}

In first step, the contract deploys the main body of DEX, with copied admin and token lambdas and "frozen" flag, and charges QUIPU tokens as deploy fees, if the sender is not whitelisted.

{% content-ref url="/pages/sELEKKRgAYLTsJ2cX37F" %}
[add\_pool](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/add_pool)
{% endcontent-ref %}

### Step 2

{% hint style="warning" %}
Underlying tokens should be approved (updated operators) before calling this method.
{% endhint %}

Step two do three operations: copy dex lambdas (as largest by size), "unfreezes" DEX, and call invest with balanced values of all underlying tokens. As the DEX pool contract had not received any investments yet, this investment is initial and equal to investing when performed [add\_pool](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/add-new-dex/add_pool)(Standalone version).

{% content-ref url="/pages/zthVkcEQQQnvLZQCg8Ga" %}
[start\_dex](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/start_dex)
{% endcontent-ref %}


# add\_pool

This entrypoint allows anyone to deploy a new own DEX pool.

{% hint style="info" %}
QUIPU token should be approved (updated operators) before calling this method.
{% endhint %}

### Call parameters

Parameters logically close to Standalone variant of [Add new dex](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/add-new-dex), but there is no "`reserves`" field in tokens\_info mapping (because invest performs at second step - [start\_dex](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/start_dex)) and some additional config parameters.

* `default_referral` - the address that would be the default referral at the new pool.
* `managers` - a set of addresses that allowed to manipulate LP token metadata at the new pool.
* `metadata` - metadata of deployed contract.
* `token_metadata`  - metadata of the LP token at the new pool.

<table><thead><tr><th width="188">Field</th><th width="247" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>a_constant</td><td align="center"><code>nat</code></td><td>constant "A" as represented as <span class="math">A*n^{n-1}</span>.</td></tr><tr><td>input_tokens</td><td align="center"><code>set(token_t)</code></td><td>sorted set of <code>FA2/FA1.2</code> tokens to add as DEX.</td></tr><tr><td>tokens_info</td><td align="center"><code>map(token_pool_idx_t,token_prec_info_t)</code></td><td>map of rates and precisions config</td></tr><tr><td>default_referral</td><td align="center"><code>address</code></td><td>default referral that will be used in operations with the referral.</td></tr><tr><td>managers</td><td align="center"><code>set(address)</code></td><td>set of managers that allowed to change LP token metadata.</td></tr><tr><td>metadata</td><td align="center"><code>big_map(string, bytes)</code></td><td>contract metadata by <a href="https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-16/tzip-16.md">TZIP-016</a></td></tr><tr><td>token_metadata</td><td align="center"><code>big_map(token_id_t, token_meta_info_t)</code></td><td>mapping each token metadata by <a href="https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-12/tzip-12.md">TZIP-012</a></td></tr></tbody></table>

```pascaligo
type token_prec_info_t  is [@layout:comb] record [
  rate                    : nat;
  precision_multiplier    : nat;
]

type pool_init_param_t  is [@layout:comb] record [
  a_constant              : nat;
  input_tokens            : set(token_t);
  tokens_info             : map(token_pool_idx_t, token_prec_info_t);
  default_referral        : address;
  managers                : set(address);
  metadata                : big_map(string, bytes);
  token_metadata          : big_map(token_id_t, token_meta_info_t);
]
```


# start\_dex

This entrypoint allows `deployer` finish setup of a new DEX pool.

Deployed pool searched by sender address (`deployer`) and passed to call tokens of `token_t` type.

{% hint style="info" %}
Underlying tokens should be approved (updated operators) before calling this method.
{% endhint %}

### Call parameters

<table><thead><tr><th width="188">Field</th><th width="247" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>start_dex_param_t</code></td><td>mapping of token index in pool to token type and amount values.</td></tr></tbody></table>

```pascaligo
type input_t_v_t        is [@layout:comb] record [
  token                   : token_t;
  value                   : nat;
]

type start_dex_param_t  is map(nat, input_t_v_t) 
```

{% hint style="warning" %}
This contract method is called only by `deployer` that called [add\_pool](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/add_pool).
{% endhint %}


# Deployed from factory DEX

This contract would be deployed after calling [add\_pool](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/add_pool) the Factory entrypoint. Contract is almost close to Standalone version of DEX contract by ABI and storage. The distinction of contracts described in [QuipuSwap stable swap DEX](/smart-contracts/quipuswap-stable-swap-dex#the-main-difference-in-implementations).

### Initialization of contract

The initialization section describes methods that are called **only** by the `Factory` contract. These methods are included in [start\_dex](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/start_dex) call and used for initial setup and start DEX pool.

{% content-ref url="/pages/WxHsEl2dwTUvVrEV7obe" %}
[Initialization](/smart-contracts/quipuswap-stable-swap-dex/factory/deployed-from-factory-dex/initialization)
{% endcontent-ref %}

### Contract storage

Storage of contract differs from Standalone only with excluding developer config in exchange of adding factory address and pausing of contract.

{% content-ref url="/pages/8C4L1YsKQUr0KzZ1kDoV" %}
[Storage and types overview](/smart-contracts/quipuswap-stable-swap-dex/factory/deployed-from-factory-dex/storage-and-types-overview)
{% endcontent-ref %}

### Core DEX methods

Main methods of DEX, that are able to use by anyone. These methods include investing, swapping, and divesting. Also, there are additional methods for staking QUIPU tokens for earning additional rewards and claiming referral rewards.

{% content-ref url="/pages/jVwwAm4e3a1fgbm6rFgP" %}
[DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods)
{% endcontent-ref %}

### Developer method

{% hint style="warning" %}
This entrypoint should be called only by `developer` address of Factory contract.&#x20;
{% endhint %}

This entrypoint is designed to claim developer rewards from a specific contract (DEX pool).

{% content-ref url="/pages/k45UEmSLmhDclXFsqRM6" %}
[claim\_developer](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/developer-methods/claim_developer)
{% endcontent-ref %}

### Admin methods

{% hint style="warning" %}
These entrypoints should be called only by `admin` address.&#x20;
{% endhint %}

The next section is about entrypoints for managing fees, "A" constant change, editing the manager list, and changing an admin address.

{% content-ref url="/pages/tjIFtpRpiwljFf1SrU53" %}
[Admin methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/admin-methods)
{% endcontent-ref %}


# Storage and types overview

Contract typings and storage

### Base types

```pascaligo
type token_id_t        is nat

type pool_id_t         is nat

type token_pool_idx_t  is nat

type fa12_token_t      is address

type fa2_token_t       is [@layout:comb] record[ 
    token_address        : address; 
    token_id             : token_id_t; 
]

type token_t           is 
| Fa12                   of fa12_token_t 
| Fa2                    of fa2_token_t

type tokens_map_t      is map(nat, token_t);
```

### Staker accumulator - accumulator of QUIPU staking rewards.

<table><thead><tr><th width="157.23880597014926">Field</th><th width="241.7580619284454" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>accumulator</td><td align="center"><code>map(token_pool_idx_t, nat)</code></td><td>For better accuracy, stored with multiplication by <span class="math">10^{10}</span>.</td><td>Mapping of token index and corresponding underlying accumulated balance of token</td></tr><tr><td>total_staked</td><td align="center"><code>nat</code></td><td></td><td>balance of staked QUIPU tokens to current pool</td></tr></tbody></table>

```pascaligo
type staker_accum_t     is [@layout:comb] record [
  accumulator             : map(token_pool_idx_t, nat);
  total_staked            : nat;
]
```

### Fee storage - fee rates record

<table><thead><tr><th width="206.35180549489237">Field</th><th width="150" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>lp</td><td align="center"><code>nat</code></td><td>Decimal value. Multiplied by <span class="math">10^{10}</span>.</td><td><p>Percent of fee goes to liquidity providers.</p><p>This fee stays in liquidity pool to increase LP token price.</p></td></tr><tr><td>stakers</td><td align="center"><code>nat</code></td><td>Decimal value. Multiplied by <span class="math">10^{10}</span>.</td><td>Percent of fee goes to QUIPU token stakers of pool. This fee goes to staking accumulator and spreads between users who staked QUIPU token to pool. If noone staked this fee part goes to liquidity pool as additional fee.</td></tr><tr><td>ref</td><td align="center"><code>nat</code></td><td>Decimal value. Multiplied by <span class="math">10^{10}</span>.</td><td>Percent of fee goes to referral of DEX call. This fee goes to referral address passed to DEX call. If referral not passed, fee goes to default referral.</td></tr></tbody></table>

```pascaligo
type fees_storage_t     is [@layout:comb] record [
  lp                      : nat;
  stakers                 : nat;
  ref                     : nat;
]
```

### Token information type - pool underlying token info

<table><thead><tr><th width="206.35180549489237">Field</th><th width="150" align="center">Type</th><th width="237">Hint</th><th>Description</th></tr></thead><tbody><tr><td>rate</td><td align="center"><code>nat</code></td><td>Calculates with pecisions. By default LP precision is 1e18. Rate is the value allowing to set custom exchange ratios between underlying tokens</td><td>Indicates how much LP token belongs to each underlying stablecoin</td></tr><tr><td>precision_multiplier</td><td align="center"><code>nat</code></td><td>By default LP precision is 1e18. Than <code>precision_multiplier</code> is <span class="math">10^{decimals_{LP} - decimals_{token}}</span></td><td>value that underlying token reserves are multiplied by in order to adjust their precision to LP decimal places</td></tr><tr><td>reserves</td><td align="center"><code>nat</code></td><td></td><td>balance of underlying token, locked in pool</td></tr></tbody></table>

```pascaligo
type token_info_t       is  [@layout:comb] record [
  rate                    : nat;
  precision_multiplier    : nat;
  reserves                : nat;
]
```

### Pool type - DEX pool storage

<table><thead><tr><th width="208.35180549489237">Field</th><th width="252" align="center">Type</th><th width="151">Hint</th><th>Description</th></tr></thead><tbody><tr><td>initial_A</td><td align="center"><code>nat</code></td><td>A constant stores as multiplied value. <span class="math"> A * n^{n-1} * 10^2</span>(10^2 is precision)</td><td>Start value of ramping A contant.</td></tr><tr><td>initial_A_time</td><td align="center"><code>timestamp</code></td><td>Timestamp in seconds</td><td>Time when ramping A constant was started.</td></tr><tr><td>future_A</td><td align="center"><code>nat</code></td><td>A constant stores as multiplied value. <span class="math"> A * n^{n-1} * 10^2</span>(10^2 is precision)</td><td>End value of ramping A contant.</td></tr><tr><td>future_A_time</td><td align="center"><code>timestamp</code></td><td>Timestamp in seconds</td><td>Time when ramping A constant will be finished</td></tr><tr><td>tokens_info</td><td align="center"><code>map(token_pool_idx_t, token_info_t)</code></td><td></td><td><a data-mention href="#token-information-type-pool-underlying-token-info">#token-information-type-pool-underlying-token-info</a></td></tr><tr><td>fee</td><td align="center"><code>fees_storage_t</code></td><td></td><td><a data-mention href="#fee-storage-fee-rates-record">#fee-storage-fee-rates-record</a></td></tr><tr><td>staker_accumulator</td><td align="center"><code>staker_accum_t</code></td><td></td><td><a data-mention href="#staker-accumulator-accumulator-of-quipu-staking-rewards.">#staker-accumulator-accumulator-of-quipu-staking-rewards.</a></td></tr><tr><td>total_supply</td><td align="center"><code>nat</code></td><td></td><td>Total supply of LP token.</td></tr></tbody></table>

```pascaligo
type pool_t             is [@layout:comb] record [
  initial_A               : nat;
  initial_A_time          : timestamp;
  future_A                : nat;
  future_A_time           : timestamp;
  tokens_info             : map(token_pool_idx_t, token_info_t);
  fee                     : fees_storage_t;
  staker_accumulator      : staker_accum_t;
  total_supply            : nat;
]
```

### Storage - main contract storage

<table><thead><tr><th width="185.35180549489237">Field</th><th width="254" align="center">Type</th><th width="233">Hint</th><th>Description</th></tr></thead><tbody><tr><td>admin</td><td align="center"><code>address</code></td><td></td><td>Administator of current contract</td></tr><tr><td>default_referral</td><td align="center"><code>address</code></td><td></td><td>Default referral address to apply fees</td></tr><tr><td>managers</td><td align="center"><code>set(address)</code></td><td>Manager could edit LP token metadata.</td><td>Set of managers addresses</td></tr><tr><td>pools_count</td><td align="center"><code>nat</code></td><td>Counter. Always <code>1</code></td><td>Amount of pools created inside current contract.</td></tr><tr><td>tokens</td><td align="center"><code>big_map(pool_id_t, tokens_map_t)</code></td><td></td><td>Mapping of tokens, that exchanges inside created pool. </td></tr><tr><td>pool_to_id</td><td align="center"><code>big_map(bytes, nat)</code></td><td>Bytes - packed by <code>Bytes.pack(tokens)</code> where tokens is valid <code>tokens_map_t</code> (sorted tokens).</td><td>Mapping that allows finding pool id by packed bytes of <code>tokens_map_t</code></td></tr><tr><td>pools</td><td align="center"><code>big_map(pool_id_t, pool_t)</code></td><td></td><td>Mapping of pool to it's corresponding pool <a data-mention href="#pool-type-dex-pool-storage">#pool-type-dex-pool-storage</a></td></tr><tr><td>ledger</td><td align="center"><p><code>big_map(</code></p><p><code>(address * pool_id_t), nat)</code></p></td><td></td><td>Mapping of user's LP token balance related to pool</td></tr><tr><td>allowances</td><td align="center"><p><code>big_map(</code></p><p><code>(address * pool_id_t), allowances_data_t)</code></p></td><td></td><td>Storage of operators allowed to transfer LP tokens of user's behalf.</td></tr><tr><td>dev_rewards</td><td align="center"><code>big_map(token_t, nat)</code></td><td></td><td>Mapping of accrued developer rewards by each token.</td></tr><tr><td>referral_rewards</td><td align="center"><p><code>big_map(</code></p><p><code>(address * token_t), nat)</code></p></td><td></td><td>Mapping of accrued referral rewards by each user-token key.</td></tr><tr><td>stakers_balance</td><td align="center"><p><code>big_map(</code></p><p><code>(address * pool_id_t), staker_info_t)</code></p></td><td></td><td>Mapping of accrued staking rewards by each user-token key.</td></tr><tr><td>quipu_token</td><td align="center"><code>fa2_token_t</code></td><td></td><td>QUIPU token address and token ID</td></tr><tr><td>started</td><td align="center"><code>bool</code></td><td><a data-mention href="/smart-contracts/quipuswap-stable-swap-dex/factory/deployed-from-factory-dex/initialization/freeze">freeze</a></td><td>flag that used in initialization stage</td></tr><tr><td>factory_address</td><td align="center"><code>address</code></td><td>this field setted at deploy and has no methods for changing</td><td>address of factory</td></tr></tbody></table>

```pascaligo
type storage_t          is [@layout:comb] record [
  (* Management *)
  admin                   : address;
  default_referral        : address;
  managers                : set(address);

  (* Pools data *)
  pools_count             : nat; (* total pools count *)
  tokens                  : big_map(pool_id_t, tokens_map_t); (* all the tokens list *)
  pool_to_id              : big_map(bytes, nat); (* all the tokens list *)
  pools                   : big_map(pool_id_t, pool_t); (* pool info per token id *)

  (* FA2 data *)
  ledger                  : big_map((address * pool_id_t), nat); (* account info per address *)
  allowances              : big_map((address * pool_id_t), allowances_data_t); (* account info per each lp provider *)

  (* Rewards and accumulators *)
  dev_rewards             : big_map(token_t, nat);
  referral_rewards        : big_map((address * token_t), nat);
  stakers_balance         : big_map((address * pool_id_t), staker_info_t);
  quipu_token             : fa2_token_t;
  (* dev storage params *)
  dev_store               : dev_storage_t;
]
```

### Full storage type - storage root

<table><thead><tr><th width="183.44565217391303">Field</th><th width="221" align="center">Type</th><th width="150">Hint</th><th>Description</th></tr></thead><tbody><tr><td>storage</td><td align="center"><code>storage_t</code></td><td><a data-mention href="#storage-main-contract-storage">#storage-main-contract-storage</a></td><td>Indicates how much LP token belongs to each underlying stablecoin</td></tr><tr><td>metadata</td><td align="center"><code>big_map(string, bytes)</code></td><td>TZIP-016</td><td>contract metadata by <a href="https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-16/tzip-16.md">TZIP-016</a></td></tr><tr><td>token_metadata</td><td align="center"><code>big_map(token_id_t, token_meta_info_t)</code></td><td>TZIP-016, TZIP-012</td><td>mapping each token metadata by <a href="https://gitlab.com/tezos/tzip/-/blob/master/proposals/tzip-12/tzip-12.md">TZIP-012</a></td></tr><tr><td>admin_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>Administrative lambda-methods storage</td></tr><tr><td>dex_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>DEX stable swap protocol lambda-methods storage</td></tr><tr><td>token_lambdas</td><td align="center"><code>big_map(nat, bytes)</code></td><td></td><td>FA2 lambda-methods storage</td></tr></tbody></table>

```pascaligo
type full_storage_t     is [@layout:comb] record [
  storage                 : storage_t; (* real dex storage_t *)
  (* Token Metadata *)
  metadata                : big_map(string, bytes); (* metadata storage_t according to TZIP-016 *)
  token_metadata          : big_map(token_id_t, token_meta_info_t);
  (* Contract lambdas storage *)
  admin_lambdas           : big_map(nat, bytes); (* map with admin-related functions code *)
  dex_lambdas             : big_map(nat, bytes); (* map with exchange-related functions code *)
  token_lambdas           : big_map(nat, bytes); (* map with token-related functions code *)
]
```


# Initialization

There are two entrypoints are responsible for initializing the new DEX pool contract.

{% hint style="warning" %}
These entrypoints should be called only by `Factory` contract address.&#x20;
{% endhint %}

Both methods are called as internal operations of one entrypoint of Factory: [start\_dex](/smart-contracts/quipuswap-stable-swap-dex/factory/initialize-new-dex-flow/start_dex).

### Copy core dex lambdas

This method receives big\_map of `nat -> bytes` - lambdas of [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods).

{% content-ref url="/pages/6iRVgFF5W18mH5TSuTJ6" %}
[copy\_dex\_function](/smart-contracts/quipuswap-stable-swap-dex/factory/deployed-from-factory-dex/initialization/copy_dex_function)
{% endcontent-ref %}

### Freeze

{% hint style="info" %}
The DEX pool contract deploys with `started = False`. This method changes this field.
{% endhint %}

This method is used only to trigger "unfreeze" of the contract after copying DEX lambdas - the last needed lambdas to enable full functionality of DEX pool.

{% content-ref url="/pages/gqwSoZDIkfkFMTiLHJAy" %}
[freeze](/smart-contracts/quipuswap-stable-swap-dex/factory/deployed-from-factory-dex/initialization/freeze)
{% endcontent-ref %}


# copy\_dex\_function

{% hint style="warning" %}
This entrypoint should be called only by `Factory` contract address.&#x20;
{% endhint %}

This method receives `big_map` of `nat -> bytes` - lambdas of [DEX methods](/smart-contracts/quipuswap-stable-swap-dex/standalone-dex/dex-methods).

### Parameters

<table><thead><tr><th width="188">Field</th><th width="247" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>big_map(nat, bytes)</code></td><td>mapping of index and bytes of DEX core methods.</td></tr></tbody></table>


# freeze

{% hint style="warning" %}
This entrypoint should be called only by `Factory` contract address.&#x20;
{% endhint %}

{% hint style="info" %}
The DEX pool contract deploys with `started = False`. This method changes this field.
{% endhint %}

This method is used only to trigger "unfreeze" of the contract after copying DEX lambdas - the last needed lambdas to enable full functionality of DEX pool.

Receives `unit` type.

Inverts value of the `started` field of contract. Called only once after setting all lambdas to DEX pool contract.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>unit</code></td><td>Empty param.</td></tr></tbody></table>


# Developer methods

{% hint style="warning" %}
These sections are called only by `developer` address.
{% endhint %}

### Claim collected deployment fees.

The Factory contract charges a deployment fee in [QUIPU](https://better-call.dev/mainnet/KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb/metadata) token. Some of the tokens got burnt and some goes to reserves. The `developer` could withdraw this fee reward.

{% hint style="info" %}
This method withdraws all the reserves in one call.&#x20;
{% endhint %}

{% content-ref url="/pages/A16jNqlk9JfEBBkxzZd9" %}
[claim\_rewards](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/claim_rewards)
{% endcontent-ref %}

### Factory management

The `developer` as admin of contract performs management of the contract. Management includes deployment fee price, burn percent, and the whitelisted addresses. Also, all params of [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module) presents inside the management section.

{% content-ref url="/pages/MBp0G1Wt3QJegyntfYEw" %}
[Factory management](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/factory-management)
{% endcontent-ref %}


# claim\_rewards

{% hint style="warning" %}
This contract method is called only by `developer` of that contract.
{% endhint %}

This entrypoint is very simple: it receives `unit` and withdraws all [QUIPU](https://better-call.dev/mainnet/KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb/metadata) tokens, collected as a deployment fee.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>unit</code></td><td>Empty param.</td></tr></tbody></table>


# Factory management

{% hint style="warning" %}
These actions are called only by `developer` address.
{% endhint %}

### Mananage deployment charges&#x20;

The Factory charges some deployment fees in [QUIPU](https://better-call.dev/mainnet/KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb/metadata) token. The `developer` can manage this fee and whitelist the specific addresses for free deployment.

{% content-ref url="/pages/VVycbFQbvBJA7Yvo0xP4" %}
[Factory params](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/factory-management/factory-params)
{% endcontent-ref %}

### Developer address and fees

The Factory contract contains [Developer module](/smart-contracts/quipuswap-stable-swap-dex/developer-module), so includes its params setters.

{% content-ref url="/pages/eA46ciGNfFQb8Yu8eg7H" %}
[Developer setter entrypoints](/smart-contracts/quipuswap-stable-swap-dex/developer-module/developer-setter-entrypoints)
{% endcontent-ref %}


# Factory params

### :money\_with\_wings:Set price

This method sets the deployment price in the [QUIPU](https://better-call.dev/mainnet/KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb/metadata) token.

{% content-ref url="/pages/9qXWMyZ7PapuVGcz5RT6" %}
[set\_price](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/factory-management/factory-params/set_price)
{% endcontent-ref %}

### :fire:Set burn rate

This method sets which percent of the deployment price will be sent to a zero address (burned).

{% content-ref url="/pages/mZ5mNCZSUCsBJaUR01V7" %}
[set\_burn\_rate](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/factory-management/factory-params/set_burn_rate)
{% endcontent-ref %}

### :white\_heart:Set whitelist

This method adds (or removes) addresses to the whitelist (for deploying new pools without charging QUIPU tokens).

{% content-ref url="/pages/41aQ1k0lwV8Jd8GJGWsI" %}
[set\_whitelist](/smart-contracts/quipuswap-stable-swap-dex/factory/developer-methods/factory-management/factory-params/set_whitelist)
{% endcontent-ref %}


# set\_burn\_rate

{% hint style="warning" %}
This contract method is called only by `developer` of that contract.
{% endhint %}

This method sets which percent of the deployment price will be sent to a zero address (burned).

Accepts `nat` value - percent of price to burn multiplied by `100_0000n`.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>nat</code></td><td>percent of price to burn (decimal value) multiplied by <code>100_0000n</code></td></tr></tbody></table>


# set\_price

{% hint style="warning" %}
This contract method is called only by `developer` of that contract.
{% endhint %}

This method sets the deployment price in the [QUIPU](https://better-call.dev/mainnet/KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb/metadata) token.

Accepts `nat` value - QUIPU token price.

### Parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>-</td><td align="center"><code>nat</code></td><td>deploy price QUIPU token.</td></tr></tbody></table>


# set\_whitelist

{% hint style="warning" %}
This contract method is called only by `developer` of that contract.
{% endhint %}

This method adds (or removes) addresses to the whitelist (for deploying new pools without charging QUIPU tokens).

### Call parameters

<table><thead><tr><th width="150">Field</th><th width="150" align="center">Type</th><th width="448.2">Description</th></tr></thead><tbody><tr><td>add</td><td align="center"><code>bool</code></td><td><code>True</code> to add or <code>False</code> to remove candidate.</td></tr><tr><td>candidate</td><td align="center"><code>address</code></td><td>address of the whitelist candidate.</td></tr></tbody></table>

```pascaligo
type set_man_param_t    is [@layout:comb] record [
  add                     : bool;
  candidate               : address;
]
```


# Dex 2.0

### About

QuipuSwap DEX 2.0 is a part of the growing QuipuSwap ecosystem. It provides a platform for better and more powerful trading. We intend to create a solution for the Tezos ecosystem akin to that Uniswap has created for Ethereum.

{% embed url="<https://github.com/madfish-solutions/quipuswap-core-v2>" %}
Code of contracts
{% endembed %}

### QuipuSwap Dex 2.0 project overview

{% content-ref url="/pages/PJIKLqS3IsyXS8Bwt7tK" %}
[DexCore contract](/smart-contracts/dex-2.0/dexcore-contract)
{% endcontent-ref %}

{% content-ref url="/pages/qclqcibCYPnhTiY5FZz5" %}
[Bucket contract](/smart-contracts/dex-2.0/bucket-contract)
{% endcontent-ref %}

{% content-ref url="/pages/Tfsg5Ntqa1tvgeBH1v4L" %}
[Auction contract](/smart-contracts/dex-2.0/auction-contract)
{% endcontent-ref %}

{% content-ref url="/pages/GjTuMWyH3WmkiJwGAhfv" %}
[FlashSwapsProxy contract](/smart-contracts/dex-2.0/flashswapsproxy-contract)
{% endcontent-ref %}

{% content-ref url="/pages/uohfRLlf1SEi9Gph8GX7" %}
[BakerRegistry contract](/smart-contracts/dex-2.0/bakerregistry-contract)
{% endcontent-ref %}

### Additional info

{% content-ref url="/pages/jHqWfeuchEKO3WMhQEWw" %}
[Errors overview](/smart-contracts/dex-2.0/errors-overview)
{% endcontent-ref %}


# Errors overview

All errors in the project are represented as string codes. The main purpose of this decision is the reduction of gas to be paid by users. Here you can find all errors codes and their explanation.

### DexCore errors

* `100` - unknown lambda function ID.
* `101` - lambda function is already set.
* `102` - wrong lambda function index (too high).
* `103` - can't unpack lambda function.
* `104` - wrong order of a tokens from parameters.
* `105` - zero token A amount in.
* `106` - zero token B amount in.
* `107` - pair (pool) with the specified `token_id` already listed.
* `108` - pair (pool) with the specified `token_id` not listed.
* `109` - pair doesn't have a liquidity.
* `110` - zero amount of LP tokens (shares) expected.
* `111` - low token A amount in.
* `112` - low token B amount in.
* `113` - a [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract not found (not TOK/TEZ LP pair).
* `114` - insufficient liquidity.
* `115` - dust output (zero tokens amount expected).
* `116` - high expectations of output tokens.
* `117` - empty route of swaps.
* `118` - zero amount in was passed as the parameter.
* `119` - wrong route of a swap.
* `120` - wrong TEZ amount were passed to the transaction.
* `121` - [***pour\_out***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/pour_out) entrypoint of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `122` - [***pour\_over***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/pour_over) entrypoint of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `123` - [***ban\_baker***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/ban_baker) entrypoint of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `124` - [***vote***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/vote) entrypoint of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `125` - [***is\_banned\_baker***](/smart-contracts/dex-2.0/bucket-contract/on-chain-views-overview/is_banned_baker) view of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `126` - [***default***](/smart-contracts/dex-2.0/flashswapsproxy-contract/entrypoints-overview/default) entrypoint of [FlashSwapsProxy](/smart-contracts/dex-2.0/flashswapsproxy-contract) contract isn't found.
* `127` - [***get\_tez\_balance***](/smart-contracts/dex-2.0/bucket-contract/on-chain-views-overview/get_tez_balance) view of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `128` - [***flash\_swap\_callback***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/callbacks/flash_swap_callback) entrypoint of [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract isn't found.
* `129` - wrong amount of flash swap returns.
* `130` - referring on yourself is forbidden.
* `131` - [***withdraw\_rewards***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/withdraw_rewards) entrypoint of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `132` - insufficient interface fee balance.
* `133` - [***get\_user\_candidate***](/smart-contracts/dex-2.0/bucket-contract/on-chain-views-overview/get_user_candidate) view of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `134` - [***launch\_callback***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/callbacks/launch_callback#launch_callback_t) entrypoint of [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract isn't found.
* `135` - [***receive\_fee***](/smart-contracts/dex-2.0/auction-contract/entrypoints-overview/auction-entrypoints/receive_fee) entrypoint of [Auction](/smart-contracts/dex-2.0/auction-contract) contract isn't found.
* `136` - reentrancy.
* `137` - [***close***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/callbacks/close) entrypoint of [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract isn't found.
* `138` - only entered (transaction must be not the first transaction in the chain of calls).
* `139` - too few swaps.
* `140` - can't perform voting because of zero LPs balance of the user.
* `141` - wrong amount of TEZ tokens were attached to transaction.
* `142` - wrong reserves state after execution of the operation.
* `143` - `pair_id` parameter not provided (in case of withdrawing TEZ tokens).
* `144` - action outdated (the time until which the transaction remained valid was passed).

### Bucket errors

* `200` - [***validate***](/smart-contracts/dex-2.0/bakerregistry-contract/entrypoints-overview/validate) entrypoint of [BakerRegistry](/smart-contracts/dex-2.0/bakerregistry-contract) contract isn't found.
* `201` - [***get\_total\_supply***](/smart-contracts/dex-2.0/dexcore-contract/on-chain-views-overview/get_total_supply) view of [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract isn't found.
* `202` - [***get\_collecting\_period***](/smart-contracts/dex-2.0/dexcore-contract/on-chain-views-overview/get_collecting_period) view of [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract isn't found.

### Auction errors

* `300` - unknown lambda function ID.
* `301` - can't unpack lambda function.
* `302` - wrong lambda function index (too high).
* `303` - lambda function is already set.
* `304` - auction with the specified ID not found.
* `305` - token for auction is whitelisted. It is not possible to start an auction with whitelisted tokens.
* `306` - token for withdrawing is NOT whitelisted.
* `307` - [Auction](/smart-contracts/dex-2.0/auction-contract) contract have insufficient balance of tokens for a new auction launch.
* `308` - user's bid is less than minimum bid for an auction launch or less that previous bid.
* `309` - auction is already finished or rewards are already claimed.
* `310` - auction is not finished.
* `311` - wrong auction duration (less than or equal to 0).

### Common errors

* `400` - `sender` of the transaction is not current administrator.
* `401` - `sender` of the transaction is not current pending administrator (not the address that was assigned by the current administrator to the shift).
* `402` - `sender` of the transaction is not a manager.
* `403` - `sender` of the transaction is not [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
* `404` - ***transfer*** entrypoint of FA12 token isn't found.
* `405` - ***transfer*** entrypoint of FA2 token isn't found.
* `406` - not a nat (not an unsigned integer).
* `407` - wrong token type.
* `408` - division by zero.
* `409` - TEZ tokens receiver contract not found (not user account or contract doesn't have a `default` entrypoint).
* `410` - [***fill***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/fill) entrypoint of [Bucket](/smart-contracts/dex-2.0/bucket-contract) contract isn't found.
* `411` - `pending_admin` in the storage of a contract is `None` (admin didn't call ***set\_admin*** entrypoint).
* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).


# BakerRegistry contract

The main purpose of this contract is registration and validation of bakers before voting during [***launch\_exchange***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/launch_exchange)*,* [***invest\_liquidity***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/invest_liquidity)*,* [***divest\_liquidity***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/divest_liquidity), [***transfer***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/fa2-entrypoints/transfer) and [***vote***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/vote) operations.


# Storage and types overview

### storage\_t - main contract storage

```pascaligo
type storage_t          is big_map(key_hash, bool)
```

<table><thead><tr><th width="150">Field</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>storage_t</td><td>big_map(key_hash, bool)</td><td>Mapping of bakers' addresses to boolean flag: baker is registered in registry or not. Only valid bakers can be registered</td></tr></tbody></table>


# Entrypoints overview

Contract have only 2 entrypoints and everyone can call both of them.

{% content-ref url="/pages/B897lHI5TpuCiZ5ME9pj" %}
[validate](/smart-contracts/dex-2.0/bakerregistry-contract/entrypoints-overview/validate)
{% endcontent-ref %}

{% content-ref url="/pages/SjMBjC4LGJ2JrqYXYT5Y" %}
[register](/smart-contracts/dex-2.0/bakerregistry-contract/entrypoints-overview/register)
{% endcontent-ref %}


# validate

An entrypoint for bakers validation. If baker is not registered and valid, he will be registered.

### Call parameters

| Field | Type      | Description           |
| ----- | --------- | --------------------- |
| baker | key\_hash | An address of a baker |

### Usage

{% tabs %}
{% tab title="🌮 Taquito" %}

```java
const bakerRegistryAddress = "KT1...";
const baker = "tz1...";
const bakerRegistry = await tezos.contract.at(bakerRegistryAddress);
const operation = await bakerRegistry.methods.validate(baker).send();

await operation.confirmation();
```

{% endtab %}
{% endtabs %}

### Errors

* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).
* the operation fails in the time of baker registration when the key\_hash parameter is not a registered delegate (standard Tezos error).


# register

An entrypoint for bakers registration.

### Call parameters

| Field | Type      | Description           |
| ----- | --------- | --------------------- |
| baker | key\_hash | An address of a baker |

### Usage

{% tabs %}
{% tab title="🌮 Taquito" %}

```javascript
const bakerRegistryAddress = "KT1...";
const baker = "tz1...";
const bakerRegistry = await tezos.contract.at(bakerRegistryAddress);
const operation = await bakerRegistry.methods.register(baker).send();

await operation.confirmation();
```

{% endtab %}
{% endtabs %}

### Errors

* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).
* the operation fails when the key\_hash parameter is not a registered delegate (standard Tezos error).


# FlashSwapsProxy contract

This is a helper contract. It is only needed in case of [***flash\_swap***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/swap) entrypoint call. It accepts a user's lambda from [***DexCore***](/smart-contracts/dex-2.0/dexcore-contract) contract and executes it.

This implementation is due to the fact that users' lambdas can be malicious for a [***DexCore***](/smart-contracts/dex-2.0/dexcore-contract) contract. And to avoid this, the execution of the users' lambdas is transferred to this ***FlashSwapProxy*** contract.


# Storage and types overview

### storage\_t - main contract storage

```pascaligo
type storage_t          is [@layout:comb] record [
  dex_core                : address;
]
```

<table><thead><tr><th width="203.51256317517502">Field</th><th width="194.1418099250341">Type</th><th>Description</th></tr></thead><tbody><tr><td>dex_core</td><td>address</td><td>Address of a DexCore contract</td></tr></tbody></table>


# Entrypoints overview

Contract have only 1 entrypoint:

{% content-ref url="/pages/HCPlobWeZyWUk1vHmK0A" %}
[default](/smart-contracts/dex-2.0/flashswapsproxy-contract/entrypoints-overview/default)
{% endcontent-ref %}

{% hint style="danger" %}
Only [***DexCore***](/smart-contracts/dex-2.0/dexcore-contract) contract can call this entrypoint.
{% endhint %}


# default

An entrypoint that accepts users' lambdas during a [***flash\_swap***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/swap) operations on [***DexCore***](/smart-contracts/dex-2.0/dexcore-contract) contract and executes them.

### Call parameters

```pascaligo
type default_t          is unit -> list(operation)
```

<table><thead><tr><th width="150">Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>default_t</td><td>unit -> list(operation)</td><td>Users's lambda function that doesn't accept any parameters (<em><strong>unit</strong></em>) and returns a list of operations (transactions, calls).</td></tr></tbody></table>

### Usage

Only [***DexCore***](/smart-contracts/dex-2.0/dexcore-contract) contract can call this entrypoint.

### Errors

* `403` - `sender` of the transaction is not [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).


# Bucket contract

Bucket contract is an auxiliary contract that is responsible for storing TEZ tokens from TOK/TEZ liquidity pools (pairs). This contract is deployed for every TOK/TEZ pair and can't be changed. In time of exchange launch or liquidity investment TEZ tokens from [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract is transferred to this contract. In time of liquidity divestment TEZ tokens returns to [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.

Bucket contract supports voting for bakers. In time of voting all TEZ tokens will be delegated to the best baker with a majority of votes. Also this baker can be changed during another vote operation.

The selected baker starts giving out baker's rewards that each user can claim (withdraw) at any time according to the number of votes that were given to the baker.

{% hint style="warning" %}
Baker can be banned by an administrator of [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract. Because of this [***vote***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/vote) operation can fail.
{% endhint %}

{% hint style="danger" %}
Almost all entrypoints on Bucket contract can be called only by [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
{% endhint %}


# Storage and types overview

### user\_reward\_info\_t

| Field           | Type | Hint                            | Description                           |
| --------------- | ---- | ------------------------------- | ------------------------------------- |
| reward\_f       | nat  | Float value multiplied by 1e+18 | Reward that must be paid to a user    |
| reward\_paid\_f | nat  | Float value multiplied by 1e+18 | Reward that is already paid to a user |

```pascaligo
type user_reward_info_t is [@layout:comb] record [
  reward_f                : nat;
  reward_paid_f           : nat;
]
```

### baker\_t

| Field            | Type      | Description                                     |
| ---------------- | --------- | ----------------------------------------------- |
| ban\_start\_time | timestamp | Start timestamp of baker's banning period       |
| ban\_period      | nat       | Banning period duration (in seconds)            |
| votes            | nat       | Amount of votes delegated to baker by all users |

```pascaligo
type baker_t            is [@layout:comb] record [
  ban_start_time          : timestamp;
  ban_period              : nat;
  votes                   : nat;
]
```

### user\_t

| Field     | Type              | Description                                       |
| --------- | ----------------- | ------------------------------------------------- |
| candidate | option(key\_hash) | Baker candidate of a user                         |
| votes     | nat               | Amount of votes delegated to the user's candidate |

```pascaligo
type user_t             is [@layout:comb] record [
  candidate               : option(key_hash);
  votes                   : nat;
]
```

### storage\_t - main contract storage

<table><thead><tr><th width="231.83783551009327">Field</th><th width="323.79608650875383">Type</th><th>Description</th></tr></thead><tbody><tr><td>users</td><td>big_map(address, <a href="#user_t">user_t</a>)</td><td>Mapping of users' addresses to theirs info</td></tr><tr><td>bakers</td><td>big_map(key_hash, <a href="#baker_t">baker_t</a>)</td><td>Mapping of bakers' addresses to theirs info</td></tr><tr><td>users_rewards</td><td>big_map(address, <a href="#undefined">user_reward_info_t</a>)</td><td>Mapping of users' addresses to theirs reward info</td></tr><tr><td>previous_delegated</td><td>key_hash</td><td>Previous delegate</td></tr><tr><td>current_delegated</td><td>key_hash</td><td>Current delegate</td></tr><tr><td>next_candidate</td><td>key_hash</td><td>Next possible delegate</td></tr><tr><td>baker_registry</td><td>address</td><td><a href="/smart-contracts/dex-2.0/bakerregistry-contract">BakerRegistry</a> contract address</td></tr><tr><td>dex_core</td><td>address</td><td><a href="/smart-contracts/dex-2.0/dexcore-contract">DexCore</a> contract address</td></tr><tr><td>pair_id</td><td>token_id_t</td><td>Pair ID on <a href="/smart-contracts/dex-2.0/dexcore-contract">DexCore</a> contract to which the current contract is linked</td></tr><tr><td>next_reward</td><td>nat</td><td>Accumulator for bakers' rewards that will be distributed between all voters</td></tr><tr><td>total_reward</td><td>nat</td><td>Total rewards that will be distributed among all voters</td></tr><tr><td>reward_paid</td><td>nat</td><td>Amount of paid to users bakers' rewards</td></tr><tr><td>reward_per_share</td><td>nat</td><td>Accumulator for reward per 1 staked token's unit</td></tr><tr><td>reward_per_block</td><td>nat</td><td>Reward per 1 block</td></tr><tr><td>last_update_level</td><td>nat</td><td>Level when a rewards were updated last time</td></tr><tr><td>collecting_period_end</td><td>nat</td><td>Level when rewards will be collected and distributed among all voters</td></tr></tbody></table>

```pascaligo
type storage_t          is [@layout:comb] record [
  users                   : big_map(address, user_t);
  bakers                  : big_map(key_hash, baker_t);
  users_rewards           : big_map(address, user_reward_info_t);
  previous_delegated      : key_hash;
  current_delegated       : key_hash;
  next_candidate          : key_hash;
  baker_registry          : address;
  dex_core                : address;
  pair_id                 : token_id_t;
  next_reward             : nat;
  total_reward            : nat;
  reward_paid             : nat;
  reward_per_share        : nat;
  reward_per_block        : nat;
  last_update_level       : nat;
  collecting_period_end   : nat;
]
```


# Entrypoints overview

Bucket contract consists of 7 entrypoints. 5 of them can be called only by [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract:

{% content-ref url="/pages/cZDNJBdHrQKD7bRcIjHc" %}
[pour\_out](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/pour_out)
{% endcontent-ref %}

{% content-ref url="/pages/HBAzIXTbuM6c6uLgRpuL" %}
[pour\_over](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/pour_over)
{% endcontent-ref %}

{% content-ref url="/pages/b7Smn5bEJ5b3YzO4qrox" %}
[withdraw\_rewards](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/withdraw_rewards)
{% endcontent-ref %}

{% content-ref url="/pages/1Ja1E9ubuA85ITplEarg" %}
[ban\_baker](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/ban_baker)
{% endcontent-ref %}

{% content-ref url="/pages/0uy7odIgGZDcbXaq68HJ" %}
[vote](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/vote)
{% endcontent-ref %}

Another 2 entrypoints can be called by everyone:

{% content-ref url="/pages/UaACXq9R7cxZPtdmjLiq" %}
[fill](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/fill)
{% endcontent-ref %}

{% content-ref url="/pages/OuD7Ai9CA8iGESPsJinH" %}
[default](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/default)
{% endcontent-ref %}


# fill

An entrypoint that accepts TEZ tokens (mostly from [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract or other Bucket contracts), stores them on the contract and doesn't affect the distribution of baker rewards.

### Call parameters

An entrypoint doesn't accept any parameters.

{% hint style="danger" %}
Note: you need to pass positive TEZ/mutez amount to the ***send()*** method (see example below).
{% endhint %}

### Usage

{% tabs %}
{% tab title="🌮 Taquito" %}

```javascript
const bucketAddress = "KT1...";
const mutezAmount = 100;
const bucket = await tezos.contract.at(bucketAddress);
const operation = await bucket.methods.fill([]).send({ amount: mutezAmount, mutez: true });

await operation.confirmation();
```

{% endtab %}
{% endtabs %}

### Errors

An entrypoint doesn't throw any errors.


# pour\_out

An entrypoint that withdraws TEZ tokens to the receiver from the parameters (mostly to the [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract).

### Call parameters

```pascaligo
type pour_out_t         is [@layout:comb] record [
  receiver                : contract(unit);
  amt                     : nat;
]
```

| Field    | Type           | Description            |
| -------- | -------------- | ---------------------- |
| receiver | contract(unit) | Receiver of TEZ tokens |
| amt      | nat            | Amount to withdraw     |

### Usage

Only [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract can call this entrypoint.

### Errors

* `403` - `sender` of the transaction is not [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).


# pour\_over

An entrypoint that sends TEZ tokens to another Bucket contract. This is necessary during the [***swap***](/smart-contracts/dex-2.0/dexcore-contract/entrypoints-overview/dex-entrypoints/swap) operation in order to immediately transfer TEZ tokens from one Bucket contract to another and not make unnecessary [***pour\_out***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/pour_out) and [***fill***](/smart-contracts/dex-2.0/bucket-contract/entrypoints-overview/fill) operations.

### Call parameters

```pascaligo
type pour_over_t        is [@layout:comb] record [
  bucket                  : address;
  amt                     : nat;
]
```

| Field  | Type    | Description                                         |
| ------ | ------- | --------------------------------------------------- |
| bucket | address | Bucket contract address for receiving of TEZ tokens |
| amt    | nat     | Amount to send                                      |

### Usage

Only [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract can call this entrypoint.

### Errors

* `403` - `sender` of the transaction is not [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).


# withdraw\_rewards

An entrypoint that updates users' global rewards. Also it updates the rewards of the user who wants to make a withdrawal. After all updates it executes a withdrawal of bakers' rewards for the specified user.

### Call parameters

```pascaligo
type withdraw_rewards_t is [@layout:comb] record [
  receiver                : contract(unit);
  user                    : address;
]
```

<table><thead><tr><th width="167.42422404731406">Field</th><th width="150">Type</th><th>Description</th></tr></thead><tbody><tr><td>receiver</td><td>contract(unit)</td><td>Receiver of TEZ tokens</td></tr><tr><td>user</td><td>address</td><td>User whose rewards need to be withdrawn</td></tr></tbody></table>

### Usage

Only [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract can call this entrypoint.

### Errors

* `403` - `sender` of the transaction is not [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).


# ban\_baker

An entrypoint that bans or unbans bakers on this Bucket contract. Voting for a banned baker is not possible.

### Call parameters

```pascaligo
type ban_baker_t        is [@layout:comb] record [
  baker                   : key_hash;
  ban_period              : nat;
]
```

| Field       | Type      | Description                         |
| ----------- | --------- | ----------------------------------- |
| baker       | key\_hash | Baker for banning or unbanning      |
| ban\_period | nat       | Period for ban (0 to unban a baker) |

### Usage

Only [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract can call this entrypoint.

### Errors

* `403` - `sender` of the transaction is not [DexCore](/smart-contracts/dex-2.0/dexcore-contract) contract.
* `412` - non payable entrypoint (can't accept TEZ tokens during call of an entrypoint).




---

[Next Page](/llms-full.txt/1)

