# What is Akronswap?

## A DEX Optimized for Restaking Interest-Bearing Tokens

Akronswap is a decentralized exchange that protects liquidity providers (LPs) from negative loss-versus-rebalancing (LVR), currently the largest type of [maximal extractable value (MEV)](https://blog.matcha.xyz/article/what-is-mev), and thus significantly reduces risks for LPs. **Because of Akronswap LP tokens' similar risk profile to interst-bearing tokens such as Aave's aTokens, Akronswap can be an optimal destination for interest-bearing token (ibToken) holders looking to restake their ibTokens to boost their yield without much change in risk.**

It is hard for conservative LPs such as interest-bearing token (ibToken) holders to restake their ibTokens to DEX because of the increased risk stemming from LVR or impermanent loss.&#x20;

<div><figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2FEY2M9eaE5MJ8ZRxdr2Ua%2Fdesmos-graph%20(34).png?alt=media&amp;token=8ff9f7bf-2bbf-4725-9f10-b1a22995647d" alt=""><figcaption><p>50% aWETH + 50% aUSDC: <br>expected APY vs. price</p></figcaption></figure> <figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2FUPDzXVPhpU1B8WGlgWET%2Fdesmos-graph%20(32).png?alt=media&amp;token=0d47e85a-2f5a-49c7-bc32-17c8c0671c1a" alt=""><figcaption><p>Traditional AMM WETH+USDC LP: <br>expected APY vs. price</p></figcaption></figure></div>

LVR is a type of MEV that affects LPs and accounts for more value loss than all other types of MEV combined. LVR costs LPs 5–7% of their liquidity, resulting in hundreds of millions lost each year.  When accounting for LVR, many of the largest liquidity pools are not profitable for LPs at all.&#x20;

Check out the clearest explainer (in just 3 minutes) of LVR yet, from LVR co-inventor and Head of Research at a16z crypto here: <https://x.com/a16zcrypto/status/1775991213268840545>. As explained by a16z, money made by arbitrageurs is exactly the money lost by LPs through adverse selection, and this money lost by LPs is called LVR.

At the moment, the [largest type of MEV is atomic swap arbitrage](https://sorellalabs.xyz/explorer?__cf_chl_tk=cBb15gX.2eKVf7kYOqGKQxGShroD7oKPGmxQVErX6Gs-1733032878-1.0.1.1-T8pcwuEmqXMImhQH4aUUaOS34WtgTjPZrkXkjw69Ry0). And research finds that 80-90% of that value is captured by non-LPs, such as arbitrageurs, block builders and proposers. On Akronswap, it is the other way around: 80-90% of that value is captured by LPs.

How does Akronswap return 80-90% of LVR back to LPs? Research predicts that next generation AMMs will recapture LVR for LPs and that [one of the primary approaches to giving LVR back to LPs is by implementing a dynamic swap fee mechanism](https://x.com/blockworksres/status/1791184174382186667). Akronswap does exactly that: implements a dynamic swap fee mechanism. In fact, Akronswap's dynamic swap fee gives back close to 100% of the LVR back to LPs so that arbitrageurs's expected profit becomes close to 0%. \[Because the expected arbitrage profit not still greater than 0, arbitrageurs still rebalance the pool's price to the market price frequently.]

The dynamic swap fee is directly proportional to swap size so it provides good execution for small swappers. If swap size is small enough, swap fees can even be less than 0.01%.&#x20;

## Summary of Benefits

#### **Liquidity providers**

* During stable market regimes, LPs earn most of the fees from frequent-small-size swaps. &#x20;
* During volatile times, LPs capture a significant percentage of the [arbitrage profits](https://crypto.news/how-mev-bots-make-multimillion-dollar-profits-from-attacks/) from arbitraguers through dynamic swap fees. &#x20;
* Because of dynamic swap fees, LPs become "passive arbitrageurs": [LPs on Akronswap stop losing money to arbitrageurs](https://x.com/jason_of_cs/status/1558510332527665154) and start earning money together with arbitrageurs.&#x20;
* Because of dynamic swap fees that is highly correlated to LVR, LPs expected APY is smoothed over changes in price. \
  \[In the graphs below, fees are underestimated in both cases because the calculation did not factor the fact that volume and thus fees usually increase with higher price change or higher volatility.] \
  \[LVR is a concept that incorporates impermanent loss (IL) and is usually greater than IL.] \
  \[The calculation for Akron APY assumes dynamic swap fees capture 80% of IL.]

<div><figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2F8NU7K62KD1HdwhynGvNH%2Fdesmos-graph%20(32).png?alt=media&amp;token=07b856ee-76fd-4053-a909-3c11cdd4ce26" alt=""><figcaption><p>Traditional AMM WETH+USDC LP: <br>expected APY vs. price</p></figcaption></figure> <figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2FF1ClkWWElotUVWcDWlDB%2Fdesmos-graph%20(39).png?alt=media&amp;token=5c34e2ab-3d63-40e0-9091-ab89fadb103b" alt=""><figcaption><p>Akronswap WETH+USDC LP: <br>expected APY vs. price</p></figcaption></figure></div>

* For the first time, because of the smoothed APY, conservative LPs such as LSTs holders and interest-bearing token (ibToken) holders can be incentivized to restake their ibTokens to Akronswap to earn more with not much change in risk. \
  \[There is obviously risk of loss from huge price changes, but that risk is significantly reduced.]

<div><figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2F4k9yht99QEL0inQmCrZ3%2Fdesmos-graph%20(37).png?alt=media&amp;token=ca103d1f-6881-4c7b-8328-a649c4a2a414" alt=""><figcaption><p>50% aWETH + 50% aUSDC: <br>expected APY vs. price</p></figcaption></figure> <figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2F7zgF9CO30Py8nz83Y3zZ%2Fdesmos-graph%20(40).png?alt=media&amp;token=cdef9377-13cf-4496-a005-0c142e926f3f" alt=""><figcaption><p>Akronswap waWETH+waUSDC LP: <br>expected APY vs. price</p></figcaption></figure></div>

#### **Swappers**

* Swappers who swap small sizes pay low dynamic swap fees. For example, if the price impact is 0.15%, [traders pay a fee of at most 0.15%](/introduction/trader-competitive-prices-for-small-swaps).&#x20;

<figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2FiSZzU04TaHU5GZ6R2MQ8%2FScreenshot%202024-12-01%20at%204.08.43%E2%80%AFPM.png?alt=media&amp;token=e03c02ff-b5e1-4fd3-889f-4fcbac39cb83" alt=""><figcaption><p>AMM with $100 million TVL vs. Akronswap V2 with $2 million: <br>Akronswap V2 offers better prices for swap size below $1500</p></figcaption></figure>

* Arbitrageurs can use Akronswap to earn profits more frequently because for small arbitrages swap fees are very low, reducing the hurdle for arbitrage.

<figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2Fca6DEwrtwTjzYKfdjemy%2FScreenshot%202024-12-01%20at%204.11.48%E2%80%AFPM.png?alt=media&amp;token=8b7ecf4c-2472-483b-a214-149727e8e12f" alt=""><figcaption><p>If there is a CEX-DEX price difference of 0.04%, an arbitrageur has an opportunity on Akronswap but not on AMM V2.</p></figcaption></figure>


# Dynamic Swap Fee Mechanism

* Below is an explanation of how dynamic swap fee is determined.&#x20;

<figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2FJW9CKZHs79fPupCpqg84%2F(Update)%20Akronswap%20Protocol.pptx%20(2).png?alt=media&amp;token=4b1e8bb9-66d3-449e-86e7-3316364aac2b" alt=""><figcaption></figcaption></figure>

* The *pool's price before swap* is equal to the price before the first swap of the block. Thus, every swap uses this reference price for the *pool's price before swap*.
* Below are a few examples of dynamic swap fee for ETH/USDC pool.

<table><thead><tr><th width="187" align="center">Price before Swap</th><th width="158" align="center">Price after swap</th><th width="157" align="center">Execution price </th><th align="center">Dynamic Swap Fee</th></tr></thead><tbody><tr><td align="center">2000 USDC</td><td align="center">2200 USDC</td><td align="center">2080 USDC</td><td align="center">$120 (6%)</td></tr><tr><td align="center">2000 USDC</td><td align="center">1999 USDC</td><td align="center">1999.02 USDC</td><td align="center">$0.02 (0.0002%)</td></tr><tr><td align="center">2000 USDC</td><td align="center">1999 USDC</td><td align="center">1999.6 USDC</td><td align="center">$0.6 (0.03%)</td></tr></tbody></table>


# LP: Source of Loss

Please bear in mind the risks, including but not limited to the following risks, when you are providing liquidity on Akronswap. We really care about your risks and that is why this sections precedes the [Source of Return](/introduction/lp-source-of-return) section.

* Loss of funds from loss-versus-rebalancing (LVR)

{% embed url="<https://a16zcrypto.com/posts/article/lvr-quantifying-the-cost-of-providing-liquidity-to-automated-market-makers/>" %}

* Loss of funds from Smart Contract Vulnerability

{% embed url="<https://oxor.io/blog/2023-12-11-cracks-in-the-code-understanding-the-vulnerabilities-of-amm-protocols/>" %}

* Loss of funds from Frontend Vulnerabilities

{% embed url="<https://massalabs.medium.com/front-end-attacks-in-web3-causes-impact-and-lessons-learned-f73d2751e953>" %}


# LP: Source of Return

Return comes from two sources.

* Lending protocol: Interest revenue by holding ibTokens
* Akronswap: swap fee revenue by restaking ibTokens to Akronswap pool

Below is an example of expected APY for Akronswap waWETH + waUSDC LP token, taking into consideration average annual LVR.

<figure><img src="https://10312106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHTx82Zw4cbBI4IvwYBeq%2Fuploads%2FUlXE3oDol7EEj4SqxvJS%2FAkronswap%20Protocol_241203%20(2).png?alt=media&amp;token=d5db1c3a-1251-41ce-91aa-913beb66b23e" alt=""><figcaption><p>LPs can lose to arbitrageurs when price changes significantly. <br>Akronswap gives close to 100% of the arbitrage profits from arbitrageurs back to LPs through dynamic swap fees.</p></figcaption></figure>

*


# Trader: Competitive prices for small swaps

**Because Akronswap has very low dynamic swap fee for a small swap sizes, it offers better prices to traders.**

For example, if Akronswap pool has $2 million in liquidity, then Akronswap offers better prices for swap sizes up to $1500 compared to a CPMMv2 that has a TVL of $80 million, 40x larger. As TVL grows, Akronswap will have better prices on larger trades because CPMMv2 collects a fixed fee of 0.25% to 0.3% whereas Akronswap collects a dynamics swap fee that can be much lower. Similarly, $10M TVL would correspond to better prices on trades up to $7500.&#x20;

Considering the median non-arbitrage swap size is between $1000 and $2000, Akronswap can offer better prices for most non-arbitrage swaps if TVL reaches a certain threshold.

👉 **See** [**Simulator**](https://docs.google.com/spreadsheets/d/1d-Vfo7QJwB5lXl2D9ukw2syghz7gxu2KYFWvPnnPTbo/edit?usp=sharing) **to compare swap costs on Akronswap vs CPMMv2 for different swap sizes and pool liquidities.**


# Vision

Our vision is to:

* provide risk-minimized incremental yield for existing conservative interest bearing token holders&#x20;
* provide incremental yield for new DEX liquidity providers<br>


# Overview

AkronSwap is an automated market maker (AMM), a decentralized exchange (DEX) that allows users to trade assets directly without the need for a traditional order book to match buyers and sellers.&#x20;

To achieve this, AkronSwap sources liquidity from users willing to loan out their assets to the protocol for a percentage of the swap fees generated when their assets are traded. These users are aptly named Liquidity Providers (LPs), and they receive Akron LP (ALP) tokens as a sort of receipt for their provided liquidity, which can be used to accumulate more yield or redeemed for the underlying deposit (plus any fees accrued on top) at any time.

Akronswap implements a dynamic swap fee structure in order to allow passive LPs to earn more by capturing a fair share of arbitrage value (or loss-versus-rebalancing from the point of view of LPs) through dynamic swap fees.

Akronswap allows only one swap per block per swap direction. This implementation ensures fair amount of dynamic swap fees are paid to LPs each block, because arbitrageurs are discouraged from splitting their swap in multiple transactions in one block in order to reduce the dynamic swap fee. The implementation also ensures that arbitrageurs are protected from sandwich attacks.


# Contracts


# V2Pair

The V2Pair contracts are responsible for all pair logic including: liquidity provision, swapping, and rebalancing the pair.

The V2Pair contract inherits ERC20 functionality, so all usual ERC20 can be used with pair tokens.

This documentation covers pool specific functionality, where the full contract can be found [here](https://github.com/akron-finance/v2-core/blob/main/contracts/UniswapV2Pair.sol).

{% hint style="info" %}
Code from [Uniswap V2 Pair](https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol) with the following modifications.

1. Introduce a new requirement in the [swap](#swap-1) function to allow only one swap per block per swap direction.
   * The new requirement ensures fair amount of dynamic swap fees are paid to LPs each block, because arbitrageurs are discouraged from splitting their swap in multiple transactions in order to manipulate the dynamic swap fee.&#x20;
   * The new requirement also ensures arbitrageurs are protected from sandwich attacks.
2. Replace the requirement\
   `balance0Adjusted` \* `balance1Adjusted` >= `reserve0` \* `reserve1` \
   in the [swap](#swap-1) function with a new requirement: \
   (net `amountIn0`) \* `balance1` >= (net `amountOut1`) \* `balance0` and,\
   (net `amountIn1`) \* `balance0` >= (net `amountOut0`) \* `balance1`.
   * The new requirement implements the dynamic swap fee structure.
     {% endhint %}

### Events[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#events) <a href="#events" id="events"></a>

#### Mint[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#mint) <a href="#mint" id="mint"></a>

```
event Mint(address indexed sender, uint amount0, uint amount1);
```

Emitted each time liquidity tokens are created via [mint](#mint-1)

#### Burn[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#burn) <a href="#burn" id="burn"></a>

```solidity
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
```

Emitted each time liquidity tokens are destroyed via [burn](#burn-1).

#### Swap[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#swap) <a href="#swap" id="swap"></a>

```solidity
event Swap(
  address indexed sender,
  uint amount0In,
  uint amount1In,
  uint amount0Out,
  uint amount1Out,
  address indexed to
);
```

Emitted each time a swap occurs via [swap](#swap-1).

#### Sync[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#sync) <a href="#sync" id="sync"></a>

```solidity
event Sync(uint112 reserve0, uint112 reserve1);
```

Emitted each time reserves are updated via [mint](#mint-1), [burn](#burn-1), [swap](#swap-1), or [sync](#sync-1).

### Read-Only Functions[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#read-only-functions) <a href="#read-only-functions" id="read-only-functions"></a>

#### MINIMUM\_LIQUIDITY[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#minimum_liquidity) <a href="#minimum_liquidity" id="minimum_liquidity"></a>

```solidity
function MINIMUM_LIQUIDITY() external pure returns (uint);
```

Returns `1000` for all pairs.

* To ameliorate rounding errors and increase the theoretical minimum tick size for liquidity provision, pairs burn the first MINIMUM\_LIQUIDITY pool tokens.
* Happens automatically during the first liquidity provision.

#### factory[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#factory) <a href="#factory" id="factory"></a>

```
function factory() external view returns (address);
```

Returns the factory address.

#### token0[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#token0) <a href="#token0" id="token0"></a>

```solidity
function token0() external view returns (address);
```

Returns the address of the pair token with the lower sort order.

#### token1[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#token1) <a href="#token1" id="token1"></a>

```solidity
function token1() external view returns (address);
```

Returns the address of the pair token with the higher sort order.

#### getReserves[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#getreserves) <a href="#getreserves" id="getreserves"></a>

```solidity
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
```

Returns the reserves of token0 and token1 used to price trades and distribute liquidity. Also returns the `block.timestamp` (mod `2**32`) of the last block during which an interaction occurred for the pair.

#### price0CumulativeLast[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#price0cumulativelast) <a href="#price0cumulativelast" id="price0cumulativelast"></a>

```solidity
function price0CumulativeLast() external view returns (uint);
```

Returns the sum of the token's price for every second in the entire history of the contract.

* Can be used to track accurate time-weighted average prices (TWAP)s across any time interval.
* The TWAP is constructed by reading the cumulative price at the beginning and at the end of the desired TWAP interval. The difference in this cumulative price can then be divided by the length of the interval to create a TWAP for that period.

#### price1CumulativeLast[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#price1cumulativelast) <a href="#price1cumulativelast" id="price1cumulativelast"></a>

```solidity
function price1CumulativeLast() external view returns (uint);
```

Returns the sum of the token's price for every second in the entire history of the contract.

#### kLast[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#klast) <a href="#klast" id="klast"></a>

```solidity
function kLast() external view returns (uint);
```

Returns the product of the reserves as of the most recent liquidity event.

### State-Changing Functions[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#state-changing-functions) <a href="#state-changing-functions" id="state-changing-functions"></a>

#### mint[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#mint-1) <a href="#mint-1" id="mint-1"></a>

```solidity
function mint(address to) external returns (uint liquidity);
```

Creates pool tokens.

* Emits [Mint](#mint), [Sync](#sync), Transfer

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#parameters)

| Name | Type    | Description                            |
| ---- | ------- | -------------------------------------- |
| `to` | address | address of the receiver of pool tokens |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#returns)

| Name        | Type | Description                        |
| ----------- | ---- | ---------------------------------- |
| `liquidity` | uint | amount of liquidity tokens created |

#### burn[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#burn-1) <a href="#burn-1" id="burn-1"></a>

```solidity
function burn(address to) external returns (uint amount0, uint amount1);
```

Destroys pool tokens.

* Emits [Burn](#burn), [Sync](#sync), Transfer

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#parameters-1)

| Name | Type    | Description                                  |
| ---- | ------- | -------------------------------------------- |
| `to` | address | address of the receiver of token0 and token1 |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#returns-1)

| Name      | Type | Description                         |
| --------- | ---- | ----------------------------------- |
| `amount0` | uint | amount of token0 returned from burn |
| `amount1` | uint | amount of token1 returned from burn |

#### swap[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#swap-1) <a href="#swap-1" id="swap-1"></a>

```solidity
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
```

Swaps tokens. For regular swaps, `data.length` must be `0`.

* Emits [Swap](#swap), [Sync](#sync).
* Either amount0Out or amount1Out will be 0 on calls depending on what the swap is from and to.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#parameters-2)

| Name         | Type    | Description                                  |
| ------------ | ------- | -------------------------------------------- |
| `amount0Out` | uint    | address of the receiver of pool tokens       |
| `amount1Out` | uint    | address of the other token in the pair       |
| `to`         | address | address of the receiver of out token         |
| `data`       | bytes   | calldata data to pass forward after the swap |

#### skim[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#skim) <a href="#skim" id="skim"></a>

```solidity
function skim(address to) external;
```

Allows a user to withdraw the difference between the current balance of the pair and `2^112 - 1` to the caller, if that difference is greater than 0.

* Used as a recovery mechanism in case enough tokens are sent to a pair to overflow the two uint112 storage slots for reserves, which could otherwise cause trades to fail.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#parameters-3)

| Name | Type    | Description               |
| ---- | ------- | ------------------------- |
| `to` | address | address to skim tokens to |

#### sync[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#sync-1) <a href="#sync-1" id="sync-1"></a>

```solidity
function sync() external;
```

Exists to set the the reserve of the contract to the current balances.

* Emits [Sync](#sync).
* Used as recovery mechanism in the case that a token asynchronously deflates the balance of a pair.

### Interface[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Pair#interface) <a href="#interface" id="interface"></a>

```solidity
pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}
```

```solidity
pragma solidity >=0.5.0;

interface IUniswapV2ERC20 {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}
```


# V2Router02

V2Router02 is used as a intermediate contract to interact with liquidity pools, or the lower level V2Pair contract. The contract can be used to swap, add liquidity, withdraw liquidity. The contract also contains many variations of these three tasks that can be used for each unique situation like using native gas tokens (i.e. ETH), and Fee-On-Transfer tokens with a tax when transfers happen.

The full contract can be found [here](https://github.com/akron-finance/v2-core/blob/main/contracts/UniswapV2Router02.sol).

### Read-Only Functions[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#read-only-functions) <a href="#read-only-functions" id="read-only-functions"></a>

#### factory[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#factory) <a href="#factory" id="factory"></a>

```solidity
function factory() external pure returns (address);
```

Returns [factory address](broken://pages/etQrlY7m9TKnPlisnxB3).

#### WETH[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#weth) <a href="#weth" id="weth"></a>

```solidity
function WETH() external pure returns (address);
```

Returns the canonical WETH address on the Ethereum [mainnet](https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2), or the canonical native wrapped address for the network the contracts are deployed on.

#### quote[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#quote) <a href="#quote" id="quote"></a>

See [quote](broken://pages/6coBeCyBJjBY7wrJwaqy#quote).

#### getAmountOut[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#getamountout) <a href="#getamountout" id="getamountout"></a>

See [getAmountOut](broken://pages/6coBeCyBJjBY7wrJwaqy#getamountout).

#### getAmountIn[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#getamountin) <a href="#getamountin" id="getamountin"></a>

See [getAmountIn](broken://pages/6coBeCyBJjBY7wrJwaqy#getamountin).

#### getAmountsOut[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#getamountsout) <a href="#getamountsout" id="getamountsout"></a>

```solidity
function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts);
```

See [getAmountsOut](broken://pages/6coBeCyBJjBY7wrJwaqy#getamountsout).

#### getAmountsIn[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#getamountsin) <a href="#getamountsin" id="getamountsin"></a>

```solidity
function getAmountsIn(uint amountOut, address[] memory path) public view returns (uint[] memory amounts);
```

See [getAmountsIn](broken://pages/6coBeCyBJjBY7wrJwaqy#getamountsin).

### State-Changing Functions[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#state-changing-functions) <a href="#state-changing-functions" id="state-changing-functions"></a>

#### addLiquidity[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#addliquidity) <a href="#addliquidity" id="addliquidity"></a>

```solidity
function addLiquidity(
  address tokenA,
  address tokenB,
  uint amountADesired,
  uint amountBDesired,
  uint amountAMin,
  uint amountBMin,
  address to,
  uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
```

Adds liquidity to an ERC-20⇄ERC-20 pool.

* To cover all possible scenarios, `msg.sender` should have already given the router an allowance of at least amountADesired/amountBDesired on tokenA/tokenB.
* Always adds assets at the ideal ratio, according to the price when the transaction is executed.
* If a pool for the passed tokens does not exists, one is created automatically, and exactly amountADesired/amountBDesired tokens are added.
* `amountAMin` and `amountBMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters)

| Name             | Type    | Description                                                                                                  |
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| `tokenA`         | address | address for one of the tokens in the pair                                                                    |
| `tokenB`         | address | address for the other token in the pair                                                                      |
| `amountADesired` | uint    | amount of tokenA to add as liquidity if the B/A price is <= amountBDesired/amountADesired (A depreciates)    |
| `amountBDesired` | uint    | amount of tokenB to add as liquidity if the A/B price is <= amountADesired/amountBDesired (B depreciates)    |
| `amountAMin`     | uint    | bounds the extent to which the B/A price can go up before the transaction reverts. Must be <= amountADesired |
| `amountBMin`     | uint    | bounds the extent to which the A/B price can go up before the transaction reverts. Must be <= amountBDesired |
| `to`             | address | recipient of the liquidity tokens                                                                            |
| `deadline`       | uint    | unix timestamp after which the transaction will revert                                                       |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns)

| Name        | Type | Description                        |
| ----------- | ---- | ---------------------------------- |
| `amountA`   | uint | amount of tokenA added to the pair |
| `amountB`   | uint | amount of tokenB added to the pair |
| `liquidity` | uint | amount of liquidity tokens minted  |

#### addLiquidityETH[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#addliquidityeth) <a href="#addliquidityeth" id="addliquidityeth"></a>

```solidity
function addLiquidityETH(
  address token,
  uint amountTokenDesired,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
```

Adds liquidity to an ERC-20⇄WETH pool with ETH.

* To cover all possible scenarios, `msg.sender` should have already given the router an allowance of at least amountTokenDesired on token.
* Always adds assets at the ideal ratio, according to the price when the transaction is executed.
* `msg.value` is treated as a amountETHDesired.
* Leftover ETH, if any, is returned to `msg.sender`.
* If a pool for the passed token and WETH does not exists, one is created automatically, and exactly amountTokenDesired/`msg.value` tokens are added.
* `amountTokenMin` and `amountETHMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-1)

| Name                 | Type    | Description                                                                                                            |
| -------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------- |
| `token`              | address | other token besides WETH in the pair                                                                                   |
| `amountTokenDesired` | uint    | amount of token to add as liquidity if the WETH/token price is <= `msg.value`/amountTokenDesired (token depreciates)   |
| `amountTokenMin`     | uint    | amount of ETH to add as liquidity if the token/WETH price is <= amountTokenDesired/`msg.value` (WETH depreciates)      |
| `amountETHMin`       | uint    | bounds the extent to which the WETH/token price can go up before the transaction reverts. Must be <= amountTokenDesire |
| `to`                 | address | recipient of the liquidity tokens                                                                                      |
| `deadline`           | uint    | unix timestamp after which the transaction will revert                                                                 |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-1)

| Name          | Type | Description                                          |
| ------------- | ---- | ---------------------------------------------------- |
| `amountToken` | uint | amount of token sent to the pair                     |
| `amountETH`   | uint | amount of ETH converted to WETH and sent to the pool |
| `liquidity`   | uint | amount of liquidity tokens minted                    |

#### removeLiquidity[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#removeliquidity) <a href="#removeliquidity" id="removeliquidity"></a>

```solidity
function removeLiquidity(
  address tokenA,
  address tokenB,
  uint liquidity,
  uint amountAMin,
  uint amountBMin,
  address to,
  uint deadline
) external returns (uint amountA, uint amountB);
```

Removes liquidity from an ERC-20⇄ERC-20 pool.

* `msg.sender` should have already given the router an allowance of at least liquidity on the pool.
* `amountAMin` and `amountBMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-2)

| Name         | Type    | Description                                                                      |
| ------------ | ------- | -------------------------------------------------------------------------------- |
| `tokenA`     | address | address for one of the tokens in the pair                                        |
| `tokenB`     | address | address for the other token in the pair                                          |
| `liquidity`  | uint    | amount of liquidity tokens to remove or burn                                     |
| `amountAMin` | uint    | minimum amount of tokenA that must be received for the transaction not to revert |
| `amountBMin` | uint    | minimum amount of tokenB that must be received for the transaction not to revert |
| `to`         | address | recipient of the underlying assets                                               |
| `deadline`   | uint    | unix timestamp after which the transaction will revert                           |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-2)

| Name      | Type | Description               |
| --------- | ---- | ------------------------- |
| `amountA` | uint | amount of tokenA received |
| `amountB` | uint | amount of tokenB received |

#### removeLiquidityETH[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#removeliquidityeth) <a href="#removeliquidityeth" id="removeliquidityeth"></a>

```solidity
function removeLiquidityETH(
  address token,
  uint liquidity,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline
) external returns (uint amountToken, uint amountETH);
```

Removes liquidity from an ERC-20⇄WETH pool and receive ETH.

* `msg.sender` should have already given the router an allowance of at least liquidity on the pool.
* `amountTokenMin` and `amountETHMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-3)

| Name             | Type    | Description                                                                     |
| ---------------- | ------- | ------------------------------------------------------------------------------- |
| `token`          | address | other token besides ETH in the pair                                             |
| `liquidity`      | uint    | amount of liquidity tokens to remove or burn                                    |
| `amountTokenMin` | uint    | minimum amount of token that must be received for the transaction not to revert |
| `amountETHMin`   | uint    | minimum amount of ETH that must be received for the transaction not to revert   |
| `to`             | uint    | recipient of the underlying assets                                              |
| `deadline`       | uint    | unix timestamp after which the transaction will revert                          |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-3)

| Name          | Type | Description              |
| ------------- | ---- | ------------------------ |
| `amountToken` | uint | amount of token received |
| `amountETH`   | uint | amount of ETH received   |

#### removeLiquidityWithPermit[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#removeliquiditywithpermit) <a href="#removeliquiditywithpermit" id="removeliquiditywithpermit"></a>

```solidity
function removeLiquidityWithPermit(
  address tokenA,
  address tokenB,
  uint liquidity,
  uint amountAMin,
  uint amountBMin,
  address to,
  uint deadline,
  bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
```

Removes liquidity from an ERC-20⇄ERC-20 pool without pre-approval.

* `amountAMin` and `amountBMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-4)

| Name         | Type    | Description                                                                        |
| ------------ | ------- | ---------------------------------------------------------------------------------- |
| `tokenA`     | address | address for one of the tokens in the pair                                          |
| `tokenB`     | address | address for the other token in the pair                                            |
| `liquidity`  | uint    | amount of liquidity tokens to remove                                               |
| `amountAMin` | uint    | minimum amount of tokenA that must be received for the transaction not to revert   |
| `amountBMin` | uint    | minimum amount of tokenB that must be received for the transaction not to revert   |
| `to`         | address | recipient of the underlying assets                                                 |
| `deadline`   | uint    | unix timestamp after which the transaction will revert                             |
| `approveMax` | bool    | whether or not the approval amount in the signature is for liquidity or `uint(-1)` |
| `v`          | uint8   | v component of the permit signature                                                |
| `r`          | bytes32 | r component of the permit signature                                                |
| `s`          | bytes32 | s component of the permit signature                                                |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-4)

| Name      | Type | Description               |
| --------- | ---- | ------------------------- |
| `amountA` | uint | amount of tokenA received |
| `amountB` | uint | amount of tokenB received |

#### removeLiquidityETHWithPermit[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#removeliquidityethwithpermit) <a href="#removeliquidityethwithpermit" id="removeliquidityethwithpermit"></a>

```solidity
function removeLiquidityETHWithPermit(
  address token,
  uint liquidity,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline,
  bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
```

Removes liquidity from an ERC-20⇄WETTH pool and receive ETH without pre-approval.

* `amountAMin` and `amountBMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-5)

| Name             | Type    | Description                                                                        |
| ---------------- | ------- | ---------------------------------------------------------------------------------- |
| `token`          | address | other token besides WETH in the pair                                               |
| `liquidity`      | uint    | amount of liquidity tokens to remove                                               |
| `amountTokenMin` | uint    | minimum amount of token that must be received for the transaction not to revert    |
| `amountETHMin`   | uint    | minimum amount of ETH that must be received for the transaction not to revert      |
| `to`             | address | recipient of the underlying assets                                                 |
| `deadline`       | uint    | unix timestamp after which the transaction will revert                             |
| `approveMax`     | bool    | whether or not the approval amount in the signature is for liquidity or `uint(-1)` |
| `v`              | uint8   | v component of the permit signature                                                |
| `r`              | bytes32 | r component of the permit signature                                                |
| `s`              | bytes32 | s component of the permit signature                                                |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-5)

| Name          | Type | Description              |
| ------------- | ---- | ------------------------ |
| `amountToken` | uint | amount of token received |
| `amountETH`   | uint | amount of ETH received   |

#### removeLiquidityETHSupportingFeeOnTransferTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#removeliquidityethsupportingfeeontransfertokens) <a href="#removeliquidityethsupportingfeeontransfertokens" id="removeliquidityethsupportingfeeontransfertokens"></a>

```solidity
function removeLiquidityETHSupportingFeeOnTransferTokens(
  address token,
  uint liquidity,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline
) external returns (uint amountETH);
```

Identical to [removeLiquidityETH](#removeliquidityeth), but succeeds for tokens that take a fee on transfer.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-6)

| Name             | Type    | Description                                                                     |
| ---------------- | ------- | ------------------------------------------------------------------------------- |
| `token`          | address | other token besides WETH in the pair                                            |
| `liquidity`      | uint    | amount of liquidity tokens to remove                                            |
| `amountTokenMin` | uint    | minimum amount of token that must be received for the transaction not to revert |
| `amountETHMin`   | uint    | minimum amount of ETH that must be received for the transaction not to revert   |
| `to`             | address | recipient of the underlying assets                                              |
| `deadline`       | uint    | unix timestamp after which the transaction will revert                          |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-6)

| Name        | Type | Description            |
| ----------- | ---- | ---------------------- |
| `amountETH` | uint | amount of ETH received |

#### removeLiquidityETHWithPermitSupportingFeeOnTransferTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#removeliquidityethwithpermitsupportingfeeontransfertokens) <a href="#removeliquidityethwithpermitsupportingfeeontransfertokens" id="removeliquidityethwithpermitsupportingfeeontransfertokens"></a>

```solidity
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
  address token,
  uint liquidity,
  uint amountTokenMin,
  uint amountETHMin,
  address to,
  uint deadline,
  bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
```

Identical to [removeLiquidityETHWithPermit](#removeliquidityethwithpermit), but succeeds for tokens that take a fee on transfer.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-7)

| Name             | Type    | Description                                                                        |
| ---------------- | ------- | ---------------------------------------------------------------------------------- |
| `token`          | address | other token besides WETH in the pair                                               |
| `liquidity`      | uint    | the amount of liquidity tokens to remove                                           |
| `amountTokenMin` | uint    | minimum amount of token that must be received for the transaction not to revert    |
| `amountETHMin`   | uint    | minimum amount of ETH that must be received for the transaction not to revert      |
| `to`             | address | recipient of the underlying assets                                                 |
| `deadline`       | uint    | unix timestamp after which the transaction will revert                             |
| `approveMax`     | bool    | whether or not the approval amount in the signature is for liquidity or `uint(-1)` |
| `v`              | uint8   | v component of the permit signature                                                |
| `r`              | bytes32 | r component of the permit signature                                                |
| `s`              | bytes32 | s component of the permit signature                                                |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-7)

| Name        | Type | Description                 |
| ----------- | ---- | --------------------------- |
| `amountETH` | uint | The amount of ETH received. |

#### swapExactTokensForTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapexacttokensfortokens) <a href="#swapexacttokensfortokens" id="swapexacttokensfortokens"></a>

```solidity
function swapExactTokensForTokens(
  uint amountIn,
  uint amountOutMin,
  address[] calldata path,
  address to,
  uint deadline
) external returns (uint[] memory amounts);
```

Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path. The first element of path is the input token, the last is the output token, and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).

* `path.length` must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
* `msg.sender` should have already given the router an allowance of at least amountIn on the input token.
* `amountOutMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-8)

| Name           | Type                | Description                                                                             |
| -------------- | ------------------- | --------------------------------------------------------------------------------------- |
| `amountIn`     | uint                | amount of input tokens to send                                                          |
| `amountOutMin` | uint                | minimum amount of output tokens that must be received for the transaction not to revert |
| `path`         | address\[] calldata | array of token addresses                                                                |
| `to`           | address             | recipient of the output tokens                                                          |
| `deadline`     | uint                | unix timestamp after which the transaction will revert                                  |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-8)

| Name      | Type           | Description                                                     |
| --------- | -------------- | --------------------------------------------------------------- |
| `amounts` | uint\[] memory | The input token amount and all subsequent output token amounts. |

#### swapTokensForExactTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swaptokensforexacttokens) <a href="#swaptokensforexacttokens" id="swaptokensforexacttokens"></a>

```solidity
function swapTokensForExactTokens(
  uint amountOut,
  uint amountInMax,
  address[] calldata path,
  address to,
  uint deadline
) external returns (uint[] memory amounts);
```

Receive an exact amount of output tokens for as few input tokens as possible, along the route determined by the path. The first element of path is the input token, the last is the output token, and any intermediate elements represent intermediate tokens to trade through (if, for example, a direct pair does not exist).

* `path.length` must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
* `msg.sender` should have already given the router an allowance of at least amountIn on the input token.
* `amountInMax` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-9)

| Name        | Type                | Description                                                                        |
| ----------- | ------------------- | ---------------------------------------------------------------------------------- |
| amountOut   | uint                | amount of output tokens to receive                                                 |
| amountInMax | uint                | maximum amount of input tokens that can be required before the transaction reverts |
| path        | address\[] calldata | array of token addresses                                                           |
| to          | address             | recipient of the output tokens                                                     |
| deadline    | uint                | unix timestamp after which the transaction will revert                             |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-9)

| Name    | Type           | Description                                                |
| ------- | -------------- | ---------------------------------------------------------- |
| amounts | uint\[] memory | input token amount and all subsequent output token amounts |

#### swapExactETHForTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapexactethfortokens) <a href="#swapexactethfortokens" id="swapexactethfortokens"></a>

```solidity
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
  external
  payable
  returns (uint[] memory amounts);
```

Swaps an exact amount of ETH for as many output tokens as possible, along the route determined by the path. The first element of path must be [WETH](#weth), the last is the output token, and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).

* `path.length` must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
* `amountOutMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-10)

| Name                   | Type                 | Description                                                                             |
| ---------------------- | -------------------- | --------------------------------------------------------------------------------------- |
| `msg.value` (amountIn) | uint                 | amount of ETH to send                                                                   |
| `amountOutMin`         | `uint`               | minimum amount of output tokens that must be received for the transaction not to revert |
| `path`                 | `address[] calldata` | array of token addresses                                                                |
| `to`                   | `address`            | recipient of the output tokens                                                          |
| `deadline`             | `uint`               | unix timestamp after which the transaction will revert                                  |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-10)

| Name    | Type            | Description                                                |
| ------- | --------------- | ---------------------------------------------------------- |
| amounts | `uint[] memory` | input token amount and all subsequent output token amounts |

#### swapTokensForExactETH[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swaptokensforexacteth) <a href="#swaptokensforexacteth" id="swaptokensforexacteth"></a>

```solidity
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
  external
  returns (uint[] memory amounts);
```

Receive an exact amount of ETH for as few input tokens as possible, along the route determined by the path. The first element of path is the input token, the last must be [WETH](#weth), and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).

* `msg.sender` should have already given the router an allowance of at least amountInMax on the input token.
* If the to address is a smart contract, it must have the ability to receive ETH.
* `path.length` must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
* `amountInMax` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-11)

| Name          | Type                | Description                                                                        |
| ------------- | ------------------- | ---------------------------------------------------------------------------------- |
| `amountOut`   | uint                | amount of ETH to receive                                                           |
| `amountInMax` | uint                | maximum amount of input tokens that can be required before the transaction reverts |
| `path`        | address\[] calldata | array of token addresses                                                           |
| `to`          | address             | recipient of ETH                                                                   |
| `deadline`    | uint                | unix timestamp after which the transaction will revert                             |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-11)

| Name      | Type           | Description                                                |
| --------- | -------------- | ---------------------------------------------------------- |
| `amounts` | uint\[] memory | input token amount and all subsequent output token amounts |

#### swapExactTokensForETH[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapexacttokensforeth) <a href="#swapexacttokensforeth" id="swapexacttokensforeth"></a>

```solidity
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
  external
  returns (uint[] memory amounts);
```

Swaps an exact amount of tokens for as much ETH as possible, along the route determined by the path. The first element of path is the input token, the last must be [WETH](#weth), and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).

* If the to address is a smart contract, it must have the ability to receive ETH.
* `path.length` must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
* `amountOutMin` can be used for slippage protection.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-12)

| Name           | Type                | Description                                                                             |
| -------------- | ------------------- | --------------------------------------------------------------------------------------- |
| `amountIn`     | uint                | amount of input tokens to send                                                          |
| `amountOutMin` | uint                | minimum amount of output tokens that must be received for the transaction not to revert |
| `path`         | address\[] calldata | array of token addresses                                                                |
| `to`           | address             | recipient of the ETH                                                                    |
| `deadline`     | uint                | unix timestamp after which the transaction will revert                                  |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-12)

| Name      | Type           | Description                                                |
| --------- | -------------- | ---------------------------------------------------------- |
| `amounts` | uint\[] memory | input token amount and all subsequent output token amounts |

#### swapETHForExactTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapethforexacttokens) <a href="#swapethforexacttokens" id="swapethforexacttokens"></a>

```solidity
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
  external
  payable
  returns (uint[] memory amounts);
```

Receive an exact amount of tokens for as little ETH as possible, along the route determined by the path. The first element of path must be [WETH](#weth), the last is the output token and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).

* Leftover ETH, if any, is returned to `msg.sender`.
* `path.length` must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
* `deadline` is used to set a time restriction on how long it can take for the tx to be executed.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-13)

| Name                      | Type                | Description                                                               |
| ------------------------- | ------------------- | ------------------------------------------------------------------------- |
| `amountOut`               | uint                | amount of tokens to receive                                               |
| `msg.value` (amountInMax) | uint                | maximum amount of ETH that can be required before the transaction reverts |
| `path`                    | address\[] calldata | array of token addresses                                                  |
| `to`                      | address             | recipient of the output tokens                                            |
| `deadline`                | uint                | unix timestamp after which the transaction will revert                    |

**Returns**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#returns-13)

| Name      | Type           | Description                                                |
| --------- | -------------- | ---------------------------------------------------------- |
| `amounts` | uint\[] memory | input token amount and all subsequent output token amounts |

#### swapExactTokensForTokensSupportingFeeOnTransferTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapexacttokensfortokenssupportingfeeontransfertokens) <a href="#swapexacttokensfortokenssupportingfeeontransfertokens" id="swapexacttokensfortokenssupportingfeeontransfertokens"></a>

```solidity
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
  uint amountIn,
  uint amountOutMin,
  address[] calldata path,
  address to,
  uint deadline
) external;
```

Identical to [swapExactTokensForTokens](#swapexacttokensfortokens), but succeeds for tokens that take a fee on transfer.

* `msg.sender` should have already given the router an allowance of at least amountIn on the input token.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-14)

| Name           | Type                | Description                                                                              |
| -------------- | ------------------- | ---------------------------------------------------------------------------------------- |
| `amountIn`     | uint                | amount of input tokens to send.                                                          |
| `amountOutMin` | uint                | minimum amount of output tokens that must be received for the transaction not to revert. |
| `path`         | address\[] calldata | array of token addresses                                                                 |
| `to`           | address             | recipient of the output tokens                                                           |
| `deadline`     | uint                | unix timestamp after which the transaction will revert                                   |

#### swapExactETHForTokensSupportingFeeOnTransferTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapexactethfortokenssupportingfeeontransfertokens) <a href="#swapexactethfortokenssupportingfeeontransfertokens" id="swapexactethfortokenssupportingfeeontransfertokens"></a>

```solidity
function swapExactETHForTokensSupportingFeeOnTransferTokens(
  uint amountOutMin,
  address[] calldata path,
  address to,
  uint deadline
) external payable;
```

Identical to [swapExactETHForTokens](#swapexactethfortokens), but succeeds for tokens that take a fee on transfer.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-15)

| Name                   | Type                | Description                                                                             |
| ---------------------- | ------------------- | --------------------------------------------------------------------------------------- |
| `msg.value` (amountIn) | uint                | amount of ETH to send                                                                   |
| `amountOutMin`         | uint                | minimum amount of output tokens that must be received for the transaction not to revert |
| `path`                 | address\[] calldata | array of token addresses                                                                |
| `to`                   | address             | recipient of the output tokens                                                          |
| `deadline`             | uint                | unix timestamp after which the transaction will revert                                  |

#### swapExactTokensForETHSupportingFeeOnTransferTokens[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#swapexacttokensforethsupportingfeeontransfertokens) <a href="#swapexacttokensforethsupportingfeeontransfertokens" id="swapexacttokensforethsupportingfeeontransfertokens"></a>

```solidity
function swapExactTokensForETHSupportingFeeOnTransferTokens(
  uint amountIn,
  uint amountOutMin,
  address[] calldata path,
  address to,
  uint deadline
) external;
```

Identical to [swapExactTokensForETH](#swapexacttokensforeth), but succeeds for tokens that take a fee on transfer.

* If the to address is a smart contract, it must have the ability to receive ETH.

**Parameters**[**​**](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#parameters-16)

| Name           | Type                | Description                                                                             |
| -------------- | ------------------- | --------------------------------------------------------------------------------------- |
| `amountIn`     | uint                | amount of input tokens to send                                                          |
| `amountOutMin` | uint                | minimum amount of output tokens that must be received for the transaction not to revert |
| `path`         | address\[] calldata | array of token addresses. `path.length` must be >= 2                                    |
| `to`           | address             | recipient of the ETH                                                                    |
| `deadline`     | uint                | unix timestamp after which the transaction will revert                                  |

### Interface[​](https://dev.sushi.com/docs/Products/Classic%20AMM/Contracts/V2Router02#interface) <a href="#interface" id="interface"></a>

```solidity
pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}
```

<br>


# Aggregator & Arbitrageur Integration

First, go through the same steps to integrate with UniswapV2.

Second, update the part of the aggregation code that calculates amountOut given amountIn and amountIn given amountOut, with reference to the following changes in the UniswapV2Library.sol contract:

#### getAmountOut

Before change

```solidity
// UniswapV2
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
    require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
    require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
    uint amountInWithFee = amountIn.mul(997);
    uint numerator = amountInWithFee.mul(reserveOut);
    uint denominator = reserveIn.mul(1000).add(amountInWithFee);
    amountOut = numerator / denominator;
}
```

After change

```solidity
// Akronswap
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
    require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
    require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
    uint numerator = reserveOut.mul(amountIn);
    uint denominator = amountIn.mul(2).add(reserveIn);        
    amountOut = numerator / denominator;
}
```

#### getAmountIn

Before change

```solidity
// UniswapV2
// given an output amount of an asset and pair reserves, returns a required input amount of the other asset
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
    require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
    require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
    uint numerator = reserveIn.mul(amountOut).mul(1000);
    uint denominator = reserveOut.sub(amountOut).mul(997);
    amountIn = (numerator / denominator).add(1);
}
```

After change

```solidity
// Akronswap
// given an output amount of an asset and pair reserves, returns a required input amount of the other asset
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
    require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
    require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
    uint numerator = reserveIn.mul(amountOut);
    uint denominator = reserveOut.sub(amountOut.mul(2));
    amountIn = (numerator / denominator).add(1);
}
```

Third, update the aggregation code to handle a reverted [swap](/technical-reference/contracts/v2pair#swap-1) transaction (a reverted transaction can occur because Akronswap allows only one swap per block), such as redirecting the swap to another pool.


# Deployment Addresses

{% tabs %}
{% tab title="Arbitrum One" %}

<table><thead><tr><th width="253.90234375">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Akron Weighted LVR Fee Hook</td><td>0xD221aFFABdD3C1281ea14C5781DEc6B0fCA8937E</td></tr><tr><td>Balancer V3 Weighted Pool Factory</td><td>0xD961E30156C2E0D0d925A0De45f931CB7815e970</td></tr><tr><td>Balancer V3 Router</td><td>0xEAedc32a51c510d35ebC11088fD5fF2b47aACF2E</td></tr><tr><td>Akron point token</td><td>0x7bEec60eF40fc2e8833cc88cc3050c7f577D76d8</td></tr></tbody></table>
{% endtab %}

{% tab title="Base" %}

<table><thead><tr><th width="254.046875">Contract</th><th>Address</th></tr></thead><tbody><tr><td>Akron Weighted LVR Fee Hook</td><td>0xA45570815dbE7BF7010c41f1f74479bE322D02bd</td></tr><tr><td>Balancer V3 Weighted Pool Factory</td><td>0x5cF4928a3205728bd12830E1840F7DB85c62a4B9</td></tr><tr><td>Balancer V3 Router</td><td>0x3f170631ed9821Ca51A59D996aB095162438DC10</td></tr></tbody></table>
{% endtab %}
{% endtabs %}


# Audits

**Akronswap Factory, Pair and Router**

* [Verichains' security audit of Akronswap](https://github.com/akron-finance/audits/blob/main/Verichains%20Public%20Report%20-%20AkronSwap.pdf) (September 2024)


# Liquidity Incentive Program

## Participate in the Liquidity Incentive Program!

{% hint style="success" %}
Deposit and earn point tokens here: <https://app.merkl.xyz/opportunities/base/ERC20/0x4Fbb7870DBE7A7Ef4866A33c0eED73D395730dc0>
{% endhint %}

{% hint style="warning" %}
During the Test Program, point tokens (AKRONp) are distributed from the [Early Liquidity Incentive](/tokenomics-tentative/distribution) allocation. The price of a point token is fixed at $2 on Merkl until a reliable source of pricing appears. With 5 million point tokens and an expected unlock of 1% of total supply of 100 million governance tokens at TGE, this would translates to $500,000 circulating supply valuation at TGE. It is recommended to conduct your own analysis before liquidity provision.&#x20;

Conservatively, please assume the price of the point token is $0 until a reliable source of pricing appears.
{% endhint %}


# Referral Program

## Share Your Referral Link! <a href="#share-your-referral-link" id="share-your-referral-link"></a>

1. Go to the ‘[Referrals](https://akronswap.com/referral)’ page and connect wallet.
2. Click your unique referral url to copy the url. Your link will look like this: <https://akronswap.com/?from=0x99999>. You can shorten your link at [https://t.ly](https://t.ly/).
3. Share your referral link over any social platform like X, Telegram, Reddit, etc.
4. Track your earned points from friends you've referred in the ‘Your Points’ section in the ‘[Referrals](https://akronswap.com/referral)’ page.

## Earn Referral Points! <a href="#earning-fee-rebates" id="earning-fee-rebates"></a>

1. You earn points when your friend provides liquidity on selected pairs on <https://merkl.angle.money/?search=akron>.&#x20;
2. Your earn 10% of the points that your friend earns. For example, if your friend provides $1000 of liquidity to ETH/USDC on Base chain for 30 days and earned 500 points, you earn 50 points.&#x20;
3. Your points will be redeemable at a 1 to 1 ratio for AKRON, the governance token from the ‘[Early Liquidity Incentive](/tokenomics-tentative/distribution)’  allocation.
4. LPs earn an extra 10% on their earned points by clicking on your unique referral link, connecting to a wallet, and then clicking on ‘Submit’ button on the pop-up window.

## Affiliate Program <a href="#affiliate-program" id="affiliate-program"></a>

Influencers with a significant audience can join our Affiliate Program for point share up to 25%.\
To become an affiliate, please fill out the form:[ ](https://forms.gle/2WCtf11qNhU7BBAe9)<https://forms.gle/2WCtf11qNhU7BBAe9>.


# Distribution

Token distribution will adhere to the following principles.

* The majority of allocation should go to LPs.
* Early Liquidity Providers should have the most benefits among all allocations.
  * Early liquidity providers who add liquidity on selected pools in the [Liquidity Incentive Program](/incentive-programs/liquidity-incentive-program#test-round-1) earn Akron point tokens (AKRONp).
  * Holders of point tokens will later be able to convert their point tokens to governance tokens, pro rata, at a conversion ratio of 1:1.&#x20;


# Risks

Akronswap has used the open source codes provided by Uniswap V2 with slight modifications. The modified code has been tested thoroughly and audited by a thrid party. However, do not trade your life savings or any assets you cannot afford to lose.

Using Akronswap has potential rewards, but it also has potential risks. Investors should conduct their own research and understand the risks involved before providing liquidity or swapping tokens on Akronswap.


