# 👋 Welcome to WarpX

## What is WarpX

WarpX is a fast, permissionless, community-aligned AMM built on MegaETH.

Users can swap tokens or earn passive yield by providing liquidity without giving up custody of their assets. WarpX focuses on simplicity, real speed, and reliability so anyone can interact with DeFi in real time on MegaETH.

## Who are we?

WarpX is created and operated by a small group of builders who believe in open access, transparency, and community-driven development. We work closely with early testers, contributors, and MegaETH ecosystem members to shape the direction of the product.

Anyone can participate by giving feedback, proposing improvements, or contributing to the codebase and documentation.

## What is the current status? <a href="#what-is-the-current-status" id="what-is-the-current-status"></a>

WarpX is live and fully functional on the MegaETH testnet with active swaps, liquidity providers, and growing volume. We are expanding the feature set, refining the user experience, and preparing the protocol for mainnet.

WarpX will continue to evolve rapidly based on community input and the unique real-time capabilities provided by MegaETH.

<br>


# Join the WarpX Community

Website: <https://warpx.exchange/>&#x20;

App: <https://testnet.warpx.exchange/>&#x20;

Twitter: <https://x.com/warpexchange>&#x20;

TG: <https://t.me/+_300oWZNXkdjNzhl>&#x20;

Discord: <https://t.co/5b3E0dCfsi>

**Support us on Fluffle:**&#x20;

1. Go to <https://www.fluffle.tools/>
2. Log in with Discord.
3. Search for "WARPX."
4. Upvote

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2Fi5Y8gxPfufQxZEc9jqp1%2Fimage.png?alt=media&amp;token=3caca0f3-89e9-409d-aff1-66066da8273c" alt=""><figcaption></figcaption></figure>


# Create a Web3 Wallet

If you do not already have a wallet, you can create one in less than two minutes.

#### Recommended options:

**MetaMask** (browser extension and mobile)

**Rabby Wallet** (browser extension and mobile)

{% stepper %}
{% step %}

### How to set up a MetaMask wallet

<https://support.metamask.io/start/getting-started-with-metamask>
{% endstep %}

{% step %}

### How to set up a Rabby wallet

<https://support.rabby.io/hc/en-us/articles/11476915889807-Get-started-with-Rabby-extension>
{% endstep %}
{% endstepper %}

*Last updated 1 year ago*


# Add the MegaETH Testnet (v2) Network

WarpX runs on the new MegaETH testnet v2.

#### Option A: Add with one click

Go to WarpX and use the Add Network button in the footer.

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2Fc3k9RMowUSNGO8iULFHf%2FWarpX-11-23-2025_05_14_PM.png?alt=media&amp;token=4d8a5e16-f136-40d5-b023-4ccd1c66f9a2" alt=""><figcaption></figcaption></figure>

#### Option B: Add manually

Chain ID: 6343 \
\
Name:  Megaeth Testnet 2 \
\
RPC: <https://timothy.megaeth.com/rpc> \
\
Explorer: <https://megaeth-testnet-v2.blockscout.com/>


# Get Testnet ETH from the Faucet

This is required to pay for testnet gas and try swaps or liquidity actions.

#### Steps

1. Visit the MegaETH v2 Timothy Faucet  (<https://docs.megaeth.com/faucet#timothy>).
2. Paste your wallet address.
3. Complete the captcha if needed.
4. Receive MegaETH testnet ETH in your wallet.

**Important:**

Do not use the old v1 faucet.

Only use the updated v2 faucet, which is posted in the important links channel.


# Make Your First Swap on WarpX

This is required to pay for testnet gas and try swaps or liquidity actions.

#### Steps

1. Go to the Swap tab.
2. Select the token you want to swap from.
3. Select the token you want to receive.
4. Enter the amount.
5. Click Swap and confirm the transaction in your wallet.
6. Your transaction will confirm very quickly since MegaETH is real time.

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2FNxasihr5Jtw3AOg56f3d%2Fimage.png?alt=media&amp;token=c3ee40c8-edfe-4769-803f-30ebacc1e81a" alt=""><figcaption></figcaption></figure>


# Add Liquidity to Earn LP Tokens

#### Steps

1. Go to the [Pools](https://testnet.warpx.exchange/pools) tab.&#x20;
2. Select a pair like [WARPX/ETH](https://testnet.warpx.exchange/pools/0x6e1e62f5d87ebae4554ddae84f72fd52bbb2912d) or any other available pool.
3. Click Add Liquidity.
4. Enter the amount of each token.
5. Confirm the transaction.
6. Receive LP tokens in your wallet.<br>

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2Fuv8xRCLA3ABombmuJpgs%2Fimage.png?alt=media&amp;token=4f8c82e1-a9cd-4dc2-b32a-a53a62ce0133" alt=""><figcaption></figcaption></figure>

These LP tokens represent your share of the pool.


# Remove Liquidity

When you want to exit your LP position:

1. Go to Pools
2. Select My Positions.
3. Choose the pool you want to exit.
4. Click Remove Liquidity.
5. Select the percentage you want to remove.
6. Confirm in your wallet.
7. You will receive your tokens back instantly.

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2FMHJaiZbmbiSBqMHSIT0P%2Fimage.png?alt=media&amp;token=1c81a874-7590-47a7-8ca1-99ee1badf963" alt=""><figcaption></figcaption></figure>


# Track Your TVL, Volume, and LP Positions

WarpX has built-in graphs that show:

* Total Value Locked
* 24-hour trading volume

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2Fy3euPcMRQUV9QdMWgnWP%2Fimage.png?alt=media&amp;token=a74ba9ac-b7f5-48a0-a6ee-3396e48cba9d" alt=""><figcaption></figcaption></figure>

* Your active liquidity positions

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2Fuchi9Q3CE2Di6NYF7QjU%2Fimage.png?alt=media&amp;token=3e791d35-488c-4837-a035-c6e007f76014" alt=""><figcaption></figcaption></figure>

You can view these inside the Pools section. (<https://testnet.warpx.exchange/pools>)


# WarpX V3

WarpX V3 brings concentrated liquidity to MegaETH with Uniswap V3–style precision.

LPs can choose price ranges, optimize capital efficiency, and earn higher fee rewards with less liquidity deployed.

Advanced AMM mechanics are now running at warp speed.


# Contracts

#### MegaETH Frontier

**Pool Class Hash:** `0x61f2973d6e0934c03c8eebd94183231225814df160044d61f4b7fa56079d4ec2`

**Factory Contract:** `0xf67cF9d6FC433e97Ec39Ae4b7E4451B56B171C8a`

**NFT Position Manager:** `0xC0c50e0445978d672EC1c785985Ea70825BC9da8`

**Swap Router:** `0x850253bc4A295D64Fb8Ea4Ed992BfF3755681251`

Quoter: `0x922B2c6e22B6C30D5d7eD86c51E395351beCF655`&#x20;

#### MegaETH Timothy Testnet

**Pool Class Hash:** `0x61f2973d6e0934c03c8eebd94183231225814df160044d61f4b7fa56079d4ec2`

**Factory Contract:** `0x125631B6B58deFD302c3314D50712E3962D817c7`

**NFT Position Manager:** `0x56173f8c6EEfA7D2aef941eafA258c341b283B8d`

**Swap Router:** `0x38BD52Fb12E7237b6E5bD7FC990a7cA197cff761`

Quoter: `0x1A71FBc3376E188804329Fdd79b259c11cf3C6A6`&#x20;


# Core


# WarpX V3 Factory

The WarpX V3 Factory enables permissionless creation of WarpX V3 liquidity pools for any ERC20 token pair.

#### Creating a New Pool <a href="#user-content-creating-a-new-pool" id="user-content-creating-a-new-pool"></a>

```
function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool)
```

Creates a liquidity pool for the given token pair and fee tier.

* Tokens can be passed in any order; they will be sorted internally
* Reverts if the pool already exists or if the fee tier is not supported
* Returns the address of the newly created pool

**Parameters:**

| Name     | Type    | Description                                              |
| -------- | ------- | -------------------------------------------------------- |
| `tokenA` | address | One of the two tokens in the pool                        |
| `tokenB` | address | The other token in the pool                              |
| `fee`    | uint24  | Fee tier (e.g., 500, 3000, 10000) in hundredths of a bip |

**Example:**

```
address pool = factory.createPool(USDC, WETH, 3000); // 0.30% fee tier
```

#### Querying Existing Pools <a href="#user-content-querying-existing-pools" id="user-content-querying-existing-pools"></a>

```
function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool)
```

Returns the pool address for a token pair and fee tier, or `address(0)` if it doesn't exist.

**Parameters:**

| Name     | Type    | Description          |
| -------- | ------- | -------------------- |
| `tokenA` | address | First token address  |
| `tokenB` | address | Second token address |
| `fee`    | uint24  | Fee tier             |

**Example:**

```
address pool = factory.getPool(USDC, WETH, 3000);require(pool != address(0), "Pool does not exist");
```

#### Checking Fee Tier Validity <a href="#user-content-checking-fee-tier-validity" id="user-content-checking-fee-tier-validity"></a>

```
function feeAmountTickSpacing(uint24 fee) external view returns (int24)
```

Returns the tick spacing for a fee tier, or `0` if the fee tier is not enabled.

**Parameters:**

| Name  | Type   | Description         |
| ----- | ------ | ------------------- |
| `fee` | uint24 | Fee amount to check |

**Example:**

```
int24 tickSpacing = factory.feeAmountTickSpacing(3000);require(tickSpacing != 0, "Fee tier not supported");
```

### Supported Fee Tiers <a href="#user-content-supported-fee-tiers" id="user-content-supported-fee-tiers"></a>

| Fee           | Tick Spacing | Use Case                             |
| ------------- | ------------ | ------------------------------------ |
| 100 (0.01%)   | 1            | Stablecoin pairs (e.g., USDC/USDT)   |
| 500 (0.05%)   | 10           | Correlated assets (e.g., WETH/stETH) |
| 3000 (0.30%)  | 60           | Most token pairs                     |
| 10000 (1.00%) | 200          | Exotic or high-volatility pairs      |


# WarpX V3 Pool

The WarpX V3 Pool contract manages concentrated liquidity positions and enables token swaps for a specific token pair and fee tier.

#### Pool Initialization <a href="#user-content-pool-initialization" id="user-content-pool-initialization"></a>

```
function initialize(uint160 sqrtPriceX96) external
```

Sets the initial price for the pool. Must be called before any liquidity can be added or swaps executed.

Price is represented as `sqrt(amountToken1/amountToken0)` in Q64.96 format.

**Parameters:**

| Name           | Type    | Description                          |
| -------------- | ------- | ------------------------------------ |
| `sqrtPriceX96` | uint160 | Initial sqrt price as a Q64.96 value |

**Example:**

```
// Initialize pool with 1:1 price ratiouint160 sqrtPrice = 79228162514264337593543950336; // sqrt(1) * 2^96pool.initialize(sqrtPrice);
```

***

#### Adding Liquidity <a href="#user-content-adding-liquidity" id="user-content-adding-liquidity"></a>

```js
function mint(    address recipient,    int24 tickLower,    int24 tickUpper,    uint128 amount,    bytes calldata data) external returns (uint256 amount0, uint256 amount1)
```

Adds liquidity for a given position. Your contract must implement `IUniswapV3MintCallback` to provide tokens.

**Parameters:**

| Name        | Type    | Description                 |
| ----------- | ------- | --------------------------- |
| `recipient` | address | Position owner address      |
| `tickLower` | int24   | Lower tick of the position  |
| `tickUpper` | int24   | Upper tick of the position  |
| `amount`    | uint128 | Amount of liquidity to mint |
| `data`      | bytes   | Data passed to the callback |

**Returns:** Token amounts required (`amount0`, `amount1`)

**Example:**

```
(uint256 amount0, uint256 amount1) = pool.mint(    msg.sender,    -887220, // Lower tick    887220,  // Upper tick    1000000, // Liquidity amount    abi.encode(msg.sender));
```

***

#### Removing Liquidity <a href="#user-content-removing-liquidity" id="user-content-removing-liquidity"></a>

```
function burn(    int24 tickLower,    int24 tickUpper,    uint128 amount) external returns (uint256 amount0, uint256 amount1)
```

Removes liquidity from a position owned by `msg.sender`.

**Parameters:**

| Name        | Type    | Description                 |
| ----------- | ------- | --------------------------- |
| `tickLower` | int24   | Lower tick of the position  |
| `tickUpper` | int24   | Upper tick of the position  |
| `amount`    | uint128 | Amount of liquidity to burn |

**Returns:** Token amounts withdrawn (`amount0`, `amount1`)

**Note:** Fees are not automatically collected. Use `collect()` to withdraw fees.

***

#### Collecting Fees <a href="#user-content-collecting-fees" id="user-content-collecting-fees"></a>

```
function collect(    address recipient,    int24 tickLower,    int24 tickUpper,    uint128 amount0Requested,    uint128 amount1Requested) external returns (uint128 amount0, uint128 amount1)
```

Collects fees and tokens owed to a position owned by `msg.sender`.

**Parameters:**

| Name               | Type    | Description                                             |
| ------------------ | ------- | ------------------------------------------------------- |
| `recipient`        | address | Address to receive tokens                               |
| `tickLower`        | int24   | Lower tick of the position                              |
| `tickUpper`        | int24   | Upper tick of the position                              |
| `amount0Requested` | uint128 | Max token0 to collect (use `type(uint128).max` for all) |
| `amount1Requested` | uint128 | Max token1 to collect (use `type(uint128).max` for all) |

**Returns:** Actual amounts collected (`amount0`, `amount1`)

**Example:**

```
// Collect all available fees(uint128 collected0, uint128 collected1) = pool.collect(    msg.sender,    tickLower,    tickUpper,    type(uint128).max,    type(uint128).max);
```

***

#### Swapping Tokens <a href="#user-content-swapping-tokens" id="user-content-swapping-tokens"></a>

```
function swap(    address recipient,    bool zeroForOne,    int256 amountSpecified,    uint160 sqrtPriceLimitX96,    bytes calldata data) external returns (int256 amount0, int256 amount1)
```

Swaps tokens in the pool. Your contract must implement `IUniswapV3SwapCallback` to provide input tokens.

**Parameters:**

| Name                | Type    | Description                                                       |
| ------------------- | ------- | ----------------------------------------------------------------- |
| `recipient`         | address | Address to receive output tokens                                  |
| `zeroForOne`        | bool    | `true` = swap token0 for token1, `false` = swap token1 for token0 |
| `amountSpecified`   | int256  | Positive = exact input, Negative = exact output                   |
| `sqrtPriceLimitX96` | uint160 | Price limit as Q64.96 (0 = no limit)                              |
| `data`              | bytes   | Data passed to the callback                                       |

**Returns:** Token deltas (`amount0`, `amount1`) - negative = tokens sent out, positive = tokens received

**Example:**

```
// Swap exactly 1000 token0 for token1(int256 amount0, int256 amount1) = pool.swap(    msg.sender,    true,              // token0 → token1    1000e18,           // Exact input amount    0,                 // No price limit    abi.encode(msg.sender));
```

***

#### Flash Loans <a href="#user-content-flash-loans" id="user-content-flash-loans"></a>

```
function flash(    address recipient,    uint256 amount0,    uint256 amount1,    bytes calldata data) external
```

Borrow tokens from the pool and repay within the same transaction. Your contract must implement `IUniswapV3FlashCallback`.

**Parameters:**

| Name        | Type    | Description                        |
| ----------- | ------- | ---------------------------------- |
| `recipient` | address | Address to receive borrowed tokens |
| `amount0`   | uint256 | Amount of token0 to borrow         |
| `amount1`   | uint256 | Amount of token1 to borrow         |
| `data`      | bytes   | Data passed to the callback        |

***

### Pool State Queries <a href="#user-content-pool-state-queries" id="user-content-pool-state-queries"></a>

#### Current Price & Tick <a href="#user-content-current-price--tick" id="user-content-current-price--tick"></a>

```
function slot0() external view returns (    uint160 sqrtPriceX96,    int24 tick,    uint16 observationIndex,    uint16 observationCardinality,    uint16 observationCardinalityNext,    uint8 feeProtocol,    bool unlocked)
```

Returns the current pool state including price and tick.

#### Liquidity <a href="#user-content-liquidity" id="user-content-liquidity"></a>

```
function liquidity() external view returns (uint128)
```

Returns the currently in-range liquidity.

#### Position Information <a href="#user-content-position-information" id="user-content-position-information"></a>

```
function positions(bytes32 key) external view returns (    uint128 liquidity,    uint256 feeGrowthInside0LastX128,    uint256 feeGrowthInside1LastX128,    uint128 tokensOwed0,    uint128 tokensOwed1)
```

Returns information about a position. The key is: `keccak256(abi.encodePacked(owner, tickLower, tickUpper))`

#### Tick Information <a href="#user-content-tick-information" id="user-content-tick-information"></a>

```
function ticks(int24 tick) external view returns (    uint128 liquidityGross,    int128 liquidityNet,    uint256 feeGrowthOutside0X128,    uint256 feeGrowthOutside1X128,    int56 tickCumulativeOutside,    uint160 secondsPerLiquidityOutsideX128,    uint32 secondsOutside,    bool initialized)
```

Returns detailed information about a specific tick.


# Periphery


# NFT Position Manager

Wraps WarpX V3 liquidity positions in ERC721 NFTs, enabling transferable and composable LP positions.

#### Creating a New Position <a href="#user-content-creating-a-new-position" id="user-content-creating-a-new-position"></a>

```
struct MintParams {    address token0;    address token1;    uint24 fee;    int24 tickLower;    int24 tickUpper;    uint256 amount0Desired;    uint256 amount1Desired;    uint256 amount0Min;    uint256 amount1Min;    address recipient;    uint256 deadline;}function mint(MintParams calldata params) external payable returns (    uint256 tokenId,    uint128 liquidity,    uint256 amount0,    uint256 amount1)
```

Creates a new liquidity position as an NFT. The pool must already exist and be initialized.

**Parameters:**

| Field            | Description                          |
| ---------------- | ------------------------------------ |
| `token0`         | First token address                  |
| `token1`         | Second token address                 |
| `fee`            | Fee tier (100, 500, 3000, or 10000)  |
| `tickLower`      | Lower tick boundary                  |
| `tickUpper`      | Upper tick boundary                  |
| `amount0Desired` | Desired amount of token0 to add      |
| `amount1Desired` | Desired amount of token1 to add      |
| `amount0Min`     | Minimum token0 (slippage protection) |
| `amount1Min`     | Minimum token1 (slippage protection) |
| `recipient`      | NFT recipient address                |
| `deadline`       | Transaction expiry timestamp         |

**Returns:** `tokenId`, `liquidity`, actual `amount0` and `amount1` deposited

**Example:**

```
INonfungiblePositionManager.MintParams memory params = INonfungiblePositionManager.MintParams({    token0: USDC,    token1: WETH,    fee: 3000,    tickLower: -887220,    tickUpper: 887220,    amount0Desired: 1000e6,    // 1000 USDC    amount1Desired: 0.5e18,    // 0.5 WETH    amount0Min: 950e6,    amount1Min: 0.475e18,    recipient: msg.sender,    deadline: block.timestamp + 300});(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) = positionManager.mint(params);
```

***

#### Increasing Liquidity <a href="#user-content-increasing-liquidity" id="user-content-increasing-liquidity"></a>

```
struct IncreaseLiquidityParams {    uint256 tokenId;    uint256 amount0Desired;    uint256 amount1Desired;    uint256 amount0Min;    uint256 amount1Min;    uint256 deadline;}function increaseLiquidity(IncreaseLiquidityParams calldata params) external payable returns (    uint128 liquidity,    uint256 amount0,    uint256 amount1)
```

Adds more liquidity to an existing position. Only the position owner can call this.

**Example:**

```
INonfungiblePositionManager.IncreaseLiquidityParams memory params =     INonfungiblePositionManager.IncreaseLiquidityParams({        tokenId: 1234,        amount0Desired: 500e6,        amount1Desired: 0.25e18,        amount0Min: 475e6,        amount1Min: 0.2375e18,        deadline: block.timestamp + 300    });(uint128 liquidity, uint256 amount0, uint256 amount1) = positionManager.increaseLiquidity(params);
```

***

#### Decreasing Liquidity <a href="#user-content-decreasing-liquidity" id="user-content-decreasing-liquidity"></a>

```
struct DecreaseLiquidityParams {    uint256 tokenId;    uint128 liquidity;    uint256 amount0Min;    uint256 amount1Min;    uint256 deadline;}function decreaseLiquidity(DecreaseLiquidityParams calldata params) external payable returns (    uint256 amount0,    uint256 amount1)
```

Removes liquidity from a position. Withdrawn tokens are credited to the position and must be collected separately.

**Example:**

```
INonfungiblePositionManager.DecreaseLiquidityParams memory params =     INonfungiblePositionManager.DecreaseLiquidityParams({        tokenId: 1234,        liquidity: 50000,        amount0Min: 100e6,        amount1Min: 0.05e18,        deadline: block.timestamp + 300    });(uint256 amount0, uint256 amount1) = positionManager.decreaseLiquidity(params);
```

***

#### Collecting Fees & Tokens <a href="#user-content-collecting-fees--tokens" id="user-content-collecting-fees--tokens"></a>

```
struct CollectParams {    uint256 tokenId;    address recipient;    uint128 amount0Max;    uint128 amount1Max;}function collect(CollectParams calldata params) external payable returns (    uint256 amount0,    uint256 amount1)
```

Collects accumulated fees and tokens from decreased liquidity.

**Example:**

```
// Collect all available tokens and feesINonfungiblePositionManager.CollectParams memory params =     INonfungiblePositionManager.CollectParams({        tokenId: 1234,        recipient: msg.sender,        amount0Max: type(uint128).max,        amount1Max: type(uint128).max    });(uint256 amount0, uint256 amount1) = positionManager.collect(params);
```

***

#### Burning a Position <a href="#user-content-burning-a-position" id="user-content-burning-a-position"></a>

```
function burn(uint256 tokenId) external payable
```

Burns an NFT position. The position must have:

* Zero liquidity remaining
* All tokens and fees collected

**Example:**

```
// Must decrease liquidity to 0 and collect all tokens firstpositionManager.burn(1234);
```

***

#### Creating & Initializing Pools <a href="#user-content-creating--initializing-pools" id="user-content-creating--initializing-pools"></a>

```
function createAndInitializePoolIfNecessary(    address token0,    address token1,    uint24 fee,    uint160 sqrtPriceX96) external payable returns (address pool)
```

Creates a new pool if it doesn't exist, and initializes it if needed. Useful for bundling with `mint()`.

**Example:**

```
// Create and initialize USDC/WETH 0.3% pool at 1:2000 ratioaddress pool = positionManager.createAndInitializePoolIfNecessary(    USDC,    WETH,    3000,    1771845812700903892492222464  // sqrt(2000) * 2^96);
```

***

### Querying Positions <a href="#user-content-querying-positions" id="user-content-querying-positions"></a>

```
function positions(uint256 tokenId) external view returns (    uint96 nonce,    address operator,    address token0,    address token1,    uint24 fee,    int24 tickLower,    int24 tickUpper,    uint128 liquidity,    uint256 feeGrowthInside0LastX128,    uint256 feeGrowthInside1LastX128,    uint128 tokensOwed0,    uint128 tokensOwed1)
```

Returns full details about a position NFT.

**Example:**

```
(    ,    ,    address token0,    address token1,    uint24 fee,    int24 tickLower,    int24 tickUpper,    uint128 liquidity,    ,    ,    uint128 tokensOwed0,    uint128 tokensOwed1) = positionManager.positions(1234);
```

***

### Events <a href="#user-content-events" id="user-content-events"></a>

#### IncreaseLiquidity <a href="#user-content-increaseliquidity" id="user-content-increaseliquidity"></a>

```
event IncreaseLiquidity(    uint256 indexed tokenId,    uint128 liquidity,    uint256 amount0,    uint256 amount1)
```

Emitted when liquidity is added to a position (including initial minting).

#### DecreaseLiquidity <a href="#user-content-decreaseliquidity" id="user-content-decreaseliquidity"></a>

```
event DecreaseLiquidity(    uint256 indexed tokenId,    uint128 liquidity,    uint256 amount0,    uint256 amount1)
```

Emitted when liquidity is removed from a position.

#### Collect <a href="#user-content-collect" id="user-content-collect"></a>

```
event Collect(    uint256 indexed tokenId,    address recipient,    uint256 amount0,    uint256 amount1)
```

Emitted when fees or tokens are collected from a position.

***

### ERC721 Compatibility <a href="#user-content-erc721-compatibility" id="user-content-erc721-compatibility"></a>

The Position Manager is a full ERC721 NFT contract, supporting:

* `transferFrom()` - Transfer positions between addresses
* `approve()` / `setApprovalForAll()` - Authorize operators
* `ownerOf()` - Query position owner
* `tokenURI()` - Get on-chain SVG metadata

Position NFTs can be traded, used as collateral, or integrated with NFT marketplaces.<br>


# Swap Router

Stateless router for executing token swaps against WarpX V3 pools with optimal routing.

#### Exact Input (Single Hop) <a href="#user-content-exact-input-single-hop" id="user-content-exact-input-single-hop"></a>

```
struct ExactInputSingleParams {    address tokenIn;    address tokenOut;    uint24 fee;    address recipient;    uint256 deadline;    uint256 amountIn;    uint256 amountOutMinimum;    uint160 sqrtPriceLimitX96;}function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut)
```

Swaps an exact amount of input tokens for as many output tokens as possible in a single pool.

**Parameters:**

| Field               | Description                           |
| ------------------- | ------------------------------------- |
| `tokenIn`           | Token to swap from                    |
| `tokenOut`          | Token to swap to                      |
| `fee`               | Pool fee tier (100, 500, 3000, 10000) |
| `recipient`         | Address to receive output tokens      |
| `deadline`          | Transaction expiry timestamp          |
| `amountIn`          | Exact amount of input tokens          |
| `amountOutMinimum`  | Minimum output (slippage protection)  |
| `sqrtPriceLimitX96` | Price limit (0 = no limit)            |

**Example:**

```
// Swap exactly 1000 USDC for WETHISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({    tokenIn: USDC,    tokenOut: WETH,    fee: 3000,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountIn: 1000e6,    amountOutMinimum: 0.4e18,  // Min 0.4 WETH    sqrtPriceLimitX96: 0});uint256 amountOut = swapRouter.exactInputSingle(params);
```

***

#### Exact Input (Multi-Hop) <a href="#user-content-exact-input-multi-hop" id="user-content-exact-input-multi-hop"></a>

```
struct ExactInputParams {    bytes path;    address recipient;    uint256 deadline;    uint256 amountIn;    uint256 amountOutMinimum;}function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut)
```

Swaps an exact amount of input tokens through multiple pools for maximum output.

**Path Encoding:**

* Format: `abi.encodePacked(tokenA, feeAB, tokenB, feeBC, tokenC)`
* Example: USDC → (3000) → WETH → (3000) → DAI

**Example:**

```
// Swap USDC → WETH → DAIbytes memory path = abi.encodePacked(USDC,uint24(3000),  // 0.3% USDC/WETH poolWETH,uint24(3000),  // 0.3% WETH/DAI pool DAI);ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({    path: path,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountIn: 1000e6,    amountOutMinimum: 950e18});uint256 amountOut = swapRouter.exactInput(params);
```

***

#### Exact Output (Single Hop) <a href="#user-content-exact-output-single-hop" id="user-content-exact-output-single-hop"></a>

```
struct ExactOutputSingleParams {
    address tokenIn;    
    address tokenOut;    
    uint24 fee;    
    address recipient;    
    uint256 deadline;    
    uint256 amountOut;    
    uint256 amountInMaximum;    
    uint160 sqrtPriceLimitX96;
}

function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn)
```

Swaps as few input tokens as possible for an exact amount of output tokens.

**Example:**

```
// Receive exactly 1 WETH, spending at most 2500 USDCISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({    tokenIn: USDC,    tokenOut: WETH,    fee: 3000,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountOut: 1e18,       // Exactly 1 WETH    amountInMaximum: 2500e6,    sqrtPriceLimitX96: 0});uint256 amountIn = swapRouter.exactOutputSingle(params);// Refund excess: if (amountIn < 2500e6) refund the difference
```

***

#### Exact Output (Multi-Hop) <a href="#user-content-exact-output-multi-hop" id="user-content-exact-output-multi-hop"></a>

```
struct ExactOutputParams {
    bytes path;
    address recipient;
    uint256 deadline;
    uint256 amountOut;
    uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn)
```

Swaps through multiple pools to receive an exact output amount.

**Path Encoding (Reversed):**

* Format: `abi.encodePacked(tokenC, feeBC, tokenB, feeAB, tokenA)`
* For USDC → WETH → DAI, encode as: DAI → WETH → USDC

**Example:**

```
// Get exactly 1000 DAI via USDC → WETH → DAIbytes memory path = abi.encodePacked(    DAI,           // Output token (reversed!)    uint24(3000),    WETH,    uint24(3000),    USDC           // Input token (reversed!));ISwapRouter.ExactOutputParams memory params = ISwapRouter.ExactOutputParams({    path: path,    recipient: msg.sender,    deadline: block.timestamp + 300,    amountOut: 1000e18,    amountInMaximum: 1050e6});uint256 amountIn = swapRouter.exactOutput(params);
```

***

### Token Approvals <a href="#user-content-token-approvals" id="user-content-token-approvals"></a>

Before swapping, approve the router to spend your tokens:

```
IERC20(tokenIn).approve(address(swapRouter), amountIn);
```

***

### Handling Native ETH <a href="#user-content-handling-native-eth" id="user-content-handling-native-eth"></a>

For ETH swaps, use WETH as `tokenIn` or `tokenOut` and send ETH with the transaction:

```
// Swap ETH for USDC
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({tokenIn: WETH,tokenOut: USDC,fee: 3000,recipient: msg.sender,deadline: block.timestamp + 300,amountIn: 1e18,amountOutMinimum: 2000e6,sqrtPriceLimitX96: 0});swapRouter.exactInputSingle{value: 1e18}(params);
```

***

### Price Limits <a href="#user-content-price-limits" id="user-content-price-limits"></a>

Set `sqrtPriceLimitX96` to prevent execution beyond a certain price:

* **Zero for one** (token0 → token1): Price cannot go below this value
* **One for zero** (token1 → token0): Price cannot go above this value
* **Set to 0**: No price limit

***

### Best Practices <a href="#user-content-best-practices" id="user-content-best-practices"></a>

1. **Always set slippage protection**: Use `amountOutMinimum` / `amountInMaximum`
2. **Use deadlines**: Set reasonable expiry times (e.g., 5 minutes)
3. **Multi-hop carefully**: More hops = more gas + more slippage
4. **Check routes**: Use off-chain router to find optimal paths
5. **Handle refunds**: For exact output swaps, refund unused input tokens

***

### Interface <a href="#user-content-interface" id="user-content-interface"></a>

```
interface ISwapRouter {
    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); 
    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
```


# ABIs


# Factory

```json
[
  {
    "inputs": [],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      },
      {
        "indexed": true,
        "internalType": "int24",
        "name": "tickSpacing",
        "type": "int24"
      }
    ],
    "name": "FeeAmountEnabled",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "oldOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnerChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token0",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "token1",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      },
      {
        "indexed": false,
        "internalType": "int24",
        "name": "tickSpacing",
        "type": "int24"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "pool",
        "type": "address"
      }
    ],
    "name": "PoolCreated",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "POOL_INIT_CODE_HASH",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "tokenA",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "tokenB",
        "type": "address"
      },
      {
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      }
    ],
    "name": "createPool",
    "outputs": [
      {
        "internalType": "address",
        "name": "pool",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      },
      {
        "internalType": "int24",
        "name": "tickSpacing",
        "type": "int24"
      }
    ],
    "name": "enableFeeAmount",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "name": "feeAmountTickSpacing",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "name": "getPool",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "parameters",
    "outputs": [
      {
        "internalType": "address",
        "name": "factory",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "token0",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "token1",
        "type": "address"
      },
      {
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      },
      {
        "internalType": "int24",
        "name": "tickSpacing",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_owner",
        "type": "address"
      }
    ],
    "name": "setOwner",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]
```


# Position Manager

```json
[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_factory",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_WETH9",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_tokenDescriptor_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "approved",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "ApprovalForAll",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "name": "Collect",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint128",
        "name": "liquidity",
        "type": "uint128"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "name": "DecreaseLiquidity",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint128",
        "name": "liquidity",
        "type": "uint128"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "name": "IncreaseLiquidity",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "DOMAIN_SEPARATOR",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "PERMIT_TYPEHASH",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "WETH9",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "baseURI",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "pure",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "burn",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "uint256",
            "name": "tokenId",
            "type": "uint256"
          },
          {
            "internalType": "address",
            "name": "recipient",
            "type": "address"
          },
          {
            "internalType": "uint128",
            "name": "amount0Max",
            "type": "uint128"
          },
          {
            "internalType": "uint128",
            "name": "amount1Max",
            "type": "uint128"
          }
        ],
        "internalType": "struct INonfungiblePositionManager.CollectParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "collect",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token0",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "token1",
        "type": "address"
      },
      {
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      },
      {
        "internalType": "uint160",
        "name": "sqrtPriceX96",
        "type": "uint160"
      }
    ],
    "name": "createAndInitializePoolIfNecessary",
    "outputs": [
      {
        "internalType": "address",
        "name": "pool",
        "type": "address"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "uint256",
            "name": "tokenId",
            "type": "uint256"
          },
          {
            "internalType": "uint128",
            "name": "liquidity",
            "type": "uint128"
          },
          {
            "internalType": "uint256",
            "name": "amount0Min",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount1Min",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          }
        ],
        "internalType": "struct INonfungiblePositionManager.DecreaseLiquidityParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "decreaseLiquidity",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "factory",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "getApproved",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "uint256",
            "name": "tokenId",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount0Desired",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount1Desired",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount0Min",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount1Min",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          }
        ],
        "internalType": "struct INonfungiblePositionManager.IncreaseLiquidityParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "increaseLiquidity",
    "outputs": [
      {
        "internalType": "uint128",
        "name": "liquidity",
        "type": "uint128"
      },
      {
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      }
    ],
    "name": "isApprovedForAll",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "token0",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "token1",
            "type": "address"
          },
          {
            "internalType": "uint24",
            "name": "fee",
            "type": "uint24"
          },
          {
            "internalType": "int24",
            "name": "tickLower",
            "type": "int24"
          },
          {
            "internalType": "int24",
            "name": "tickUpper",
            "type": "int24"
          },
          {
            "internalType": "uint256",
            "name": "amount0Desired",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount1Desired",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount0Min",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amount1Min",
            "type": "uint256"
          },
          {
            "internalType": "address",
            "name": "recipient",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          }
        ],
        "internalType": "struct INonfungiblePositionManager.MintParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "mint",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "uint128",
        "name": "liquidity",
        "type": "uint128"
      },
      {
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes[]",
        "name": "data",
        "type": "bytes[]"
      }
    ],
    "name": "multicall",
    "outputs": [
      {
        "internalType": "bytes[]",
        "name": "results",
        "type": "bytes[]"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ownerOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "permit",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "positions",
    "outputs": [
      {
        "internalType": "uint96",
        "name": "nonce",
        "type": "uint96"
      },
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "token0",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "token1",
        "type": "address"
      },
      {
        "internalType": "uint24",
        "name": "fee",
        "type": "uint24"
      },
      {
        "internalType": "int24",
        "name": "tickLower",
        "type": "int24"
      },
      {
        "internalType": "int24",
        "name": "tickUpper",
        "type": "int24"
      },
      {
        "internalType": "uint128",
        "name": "liquidity",
        "type": "uint128"
      },
      {
        "internalType": "uint256",
        "name": "feeGrowthInside0LastX128",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "feeGrowthInside1LastX128",
        "type": "uint256"
      },
      {
        "internalType": "uint128",
        "name": "tokensOwed0",
        "type": "uint128"
      },
      {
        "internalType": "uint128",
        "name": "tokensOwed1",
        "type": "uint128"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "refundETH",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      },
      {
        "internalType": "bytes",
        "name": "_data",
        "type": "bytes"
      }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "selfPermit",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "nonce",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "expiry",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "selfPermitAllowed",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "nonce",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "expiry",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "selfPermitAllowedIfNecessary",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "selfPermitIfNecessary",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "operator",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "approved",
        "type": "bool"
      }
    ],
    "name": "setApprovalForAll",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes4",
        "name": "interfaceId",
        "type": "bytes4"
      }
    ],
    "name": "supportsInterface",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amountMinimum",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "sweepToken",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "index",
        "type": "uint256"
      }
    ],
    "name": "tokenByIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "index",
        "type": "uint256"
      }
    ],
    "name": "tokenOfOwnerByIndex",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "tokenURI",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amount0Owed",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1Owed",
        "type": "uint256"
      },
      {
        "internalType": "bytes",
        "name": "data",
        "type": "bytes"
      }
    ],
    "name": "uniswapV3MintCallback",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amountMinimum",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "unwrapWETH9",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]
```


# SwapRouter

```json
[
  {
    "inputs": [
      {
        "name": "data",
        "type": "bytes[]"
      }
    ],
    "name": "multicall",
    "outputs": [
      {
        "name": "results",
        "type": "bytes[]"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "tokenIn",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "tokenOut",
            "type": "address"
          },
          {
            "internalType": "uint24",
            "name": "fee",
            "type": "uint24"
          },
          {
            "internalType": "address",
            "name": "recipient",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountIn",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountOutMinimum",
            "type": "uint256"
          },
          {
            "internalType": "uint160",
            "name": "sqrtPriceLimitX96",
            "type": "uint160"
          }
        ],
        "internalType": "struct ISwapRouter.ExactInputSingleParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "exactInputSingle",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amountOut",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "tokenIn",
            "type": "address"
          },
          {
            "internalType": "address",
            "name": "tokenOut",
            "type": "address"
          },
          {
            "internalType": "uint24",
            "name": "fee",
            "type": "uint24"
          },
          {
            "internalType": "address",
            "name": "recipient",
            "type": "address"
          },
          {
            "internalType": "uint256",
            "name": "deadline",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountOut",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "amountInMaximum",
            "type": "uint256"
          },
          {
            "internalType": "uint160",
            "name": "sqrtPriceLimitX96",
            "type": "uint160"
          }
        ],
        "internalType": "struct ISwapRouter.ExactOutputSingleParams",
        "name": "params",
        "type": "tuple"
      }
    ],
    "name": "exactOutputSingle",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amountIn",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amountMinimum",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "unwrapWETH9",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "refundETH",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  }
]
```


# Pool

```json
[
  {
    "inputs": [],
    "name": "slot0",
    "outputs": [
      {
        "internalType": "uint160",
        "name": "sqrtPriceX96",
        "type": "uint160"
      },
      {
        "internalType": "int24",
        "name": "tick",
        "type": "int24"
      },
      {
        "internalType": "uint16",
        "name": "observationIndex",
        "type": "uint16"
      },
      {
        "internalType": "uint16",
        "name": "observationCardinality",
        "type": "uint16"
      },
      {
        "internalType": "uint16",
        "name": "observationCardinalityNext",
        "type": "uint16"
      },
      {
        "internalType": "uint8",
        "name": "feeProtocol",
        "type": "uint8"
      },
      {
        "internalType": "bool",
        "name": "unlocked",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "liquidity",
    "outputs": [
      {
        "internalType": "uint128",
        "name": "",
        "type": "uint128"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tickSpacing",
    "outputs": [
      {
        "internalType": "int24",
        "name": "",
        "type": "int24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "fee",
    "outputs": [
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "token0",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "token1",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "feeGrowthGlobal0X128",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "feeGrowthGlobal1X128",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "int24",
        "name": "tick",
        "type": "int24"
      }
    ],
    "name": "ticks",
    "outputs": [
      {
        "internalType": "uint128",
        "name": "liquidityGross",
        "type": "uint128"
      },
      {
        "internalType": "int128",
        "name": "liquidityNet",
        "type": "int128"
      },
      {
        "internalType": "uint256",
        "name": "feeGrowthOutside0X128",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "feeGrowthOutside1X128",
        "type": "uint256"
      },
      {
        "internalType": "int56",
        "name": "tickCumulativeOutside",
        "type": "int56"
      },
      {
        "internalType": "uint160",
        "name": "secondsPerLiquidityOutsideX128",
        "type": "uint160"
      },
      {
        "internalType": "uint32",
        "name": "secondsOutside",
        "type": "uint32"
      },
      {
        "internalType": "bool",
        "name": "initialized",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]
```


# WarpX V2

WarpX V2 is our classic constant product AMM built for real-time trading on MegaETH.

It delivers instant swaps, simple LP management, and zero-friction performance powered by the fastest chain in existence.

A familiar DEX experience, upgraded for speed.


# Contracts

**MegaETH Frontier**

* Factory: `0xB3Ae00A68F09E8b8a003B7669e2E84544cC4a385`
* Router: `0x2Fcb75d7dDea4CEa87e77Aa69Fb9d3c4CD93Deb5`
* Wrapped native (WMEGAETH): `0x4200000000000000000000000000000000000006`

**MegaETH Testnet V2 (Timothy)**

* Factory: `0x4C40BA03b676bc14bFC8A7DAeBc361C05CbB6867`
* Router: `0x687f67Ce9Ec3D221B4A7d0d7D7D1186DFC32a678`
* Wrapped native (WMEGAETH): `0xA51EbEdb0970133D016444Be0049efFE9257D06A`


# Core

#### WarpFactory

Source: `packages/core/contracts/WarpFactory.sol`

Responsibilities:

* Deploys every `WarpPair` (using `CREATE2`) and records them in the `getPair` mapping.
* Exposes `INIT_CODE_PAIR_HASH = 0x0904716a2e7c34f649f3837f2424539ef9f2c8cc5ba0d9d55ed439d013b94ce0` deterministic pair address derivation.

Key functions:

<table><thead><tr><th width="374.99609375">Signature</th><th>Usage</th></tr></thead><tbody><tr><td><code>function allPairsLength() external view returns (uint)</code></td><td>Count pairs for pagination.</td></tr><tr><td><code>function getPair(address tokenA, address tokenB) external view returns (address)</code></td><td>Query existing pair (tokens sorted internally).</td></tr><tr><td><code>function createPair(address tokenA, address tokenB) external returns (address pair)</code></td><td>Deploys a new pair. Reverts on identical/zero addresses or if the pair already exists.</td></tr></tbody></table>

Event: `PairCreated(token0, token1, pair, pairIndex)` fires whenever a new pool is deployed. Listen to this to surface freshly created pools without polling.

#### WarpPair

Source: `packages/core/contracts/WarpPair.sol`

Warp LP tokens implement `IWarpPair` + ERC-20 + EIP-2612 permit. Highlights:

* Immutable token ordering: `token0`, `token1` stored on initialization.
* `getReserves()` returns reserves and the timestamp of the last sync for TWAP calculations.
* `MINIMUM_LIQUIDITY = 1_000` LP tokens are permanently locked to prevent divide-by-zero on the initial liquidity event.
* Fees: 0.30% swap fee (997/1000 factor) with optional protocol fee (mints 1/6 of √k growth to `feeTo` if set).
* Flash swaps: `swap()` accepts arbitrary `data`; if `data.length > 0`, it callbacks `IWarpCallee.warpCall(sender, amount0Out, amount1Out, data)`. Return the owed tokens before the function completes.
* Housekeeping helpers: `skim(address)` sends any excess tokens (beyond reserves) to `to`, `sync()` forcibly updates reserves to match balances.

Key entrypoints and why integrators use them:

| Signature                                                                          | Purpose                                                                                                                  |
| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `function mint(address to) external returns (uint liquidity)`                      | Called by the router after tokens have been transferred in. Returns LP tokens minted to `to`.                            |
| `function burn(address to) external returns (uint amount0, uint amount1)`          | Burns LP tokens held by the pair and sends out the underlying assets.                                                    |
| `function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data)` | Core swap primitive. Either `amount0Out` or `amount1Out` must be > 0. Caller must have already sent the input tokens in. |
| `function permit(...) external`                                                    | Enables gasless approvals so `removeLiquidityWithPermit` can operate without a prior `approve`.                          |
| `function getReserves()` + `price0CumulativeLast/price1CumulativeLast`             | Fetch raw reserves and cumulative price data for off-chain quoting/TWAPs.                                                |

Events worth indexing: `Mint`, `Burn`, `Swap`, `Sync`, and standard ERC-20 `Transfer`/`Approval`.


# Periphery

#### WarpRouter02 (Router)

Source: `packages/periphery/contracts/WarpRouter.sol` implementing `IWarpRouter02`.

State: immutable `factory()` and `WETH()` addresses; reverts if `deadline < block.timestamp` on any user-facing method.

**Liquidity Management**

* `addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin, to, deadline)`
  * Approvals required for both tokens to the router.
  * If the pair does not exist, the router creates it on the fly via the factory.
  * Internally balances desired inputs using `WarpLibrary.quote` so slippage bounds (`amountA/BMin`) must be set around expected ratios.
* `addLiquidityETH(token, amountTokenDesired, amountTokenMin, amountETHMin, to, deadline)` (payable)
  * Wraps native ETH into WETH before forwarding into the pair.
  * Refunds surplus ETH to the sender.
* `removeLiquidity(...)` and `removeLiquidityETH(...)`
  * Transfer LP tokens from the caller to the pair, burn them, and distribute assets to `to`.
  * ETH variant unwraps WETH before final transfer.
* Permit variants: `removeLiquidityWithPermit` + `removeLiquidityETHWithPermit` accept EIP-2612 signatures so integrators can batch approve-and-remove in one call.

**Liquidity for Fee-On-Transfer Tokens**

`removeLiquidityETHSupportingFeeOnTransferTokens` and `removeLiquidityETHWithPermitSupportingFeeOnTransferTokens` handle tokens that tax transfers by re-checking router balances instead of the raw burn return values.

**Swap Entry Points**

All swap functions expect an ordered `path` of at least two addresses. The router handles wiring funds between intermediate pairs and enforces min/max slippage via `amountOutMin`/`amountInMax`. Available combinations:

* `swapExactTokensForTokens`
* `swapTokensForExactTokens`
* `swapExactETHForTokens` (payable)
* `swapTokensForExactETH`
* `swapExactTokensForETH`
* `swapETHForExactTokens` (payable)

Fee-on-transfer safe variants (`swapExactTokensForTokensSupportingFeeOnTransferTokens`, `swapExactETHForTokensSupportingFeeOnTransferTokens`, `swapExactTokensForETHSupportingFeeOnTransferTokens`) read the received balance instead of trusting pair outputs.

**Pricing Helpers**

Integrators can quote trades or rebalance liquidity without touching the chain via:

* `quote(amountA, reserveA, reserveB)` – deterministic price quote.
* `getAmountOut(amountIn, reserveIn, reserveOut)` and `getAmountIn(amountOut, reserveIn, reserveOut)` – expose the 0.30% fee curve.
* `getAmountsOut(amountIn, path)` and `getAmountsIn(amountOut, path)` – chain-aware quoting across multiple hops.

These mirror functions in `WarpLibrary` so any SDK code can reuse the same math off-chain.

#### WarpRouter01

`packages/periphery/contracts/WarpRouter01.sol` is a slimmer router that omits fee-on-transfer helpers. Use it only if you require a byte-identical clone of the Uniswap v2 router v1 interface; otherwise `WarpRouter02` (above) is the canonical deployment.

#### WarpMigrator

Source: `packages/periphery/contracts/WarpMigrator.sol`

Single `migrate(token, amountTokenMin, amountETHMin, to, deadline)` entrypoint:

1. Pulls the caller’s entire V1 LP position from the V1 exchange (requires prior approval to the migrator).
2. Removes V1 liquidity and captures the token/ETH amounts.
3. Approves the v2 router for those tokens and adds v2 liquidity via `addLiquidityETH`, respecting the caller’s min amounts.
4. Refunds any excess tokens or ETH back to the caller.

Route bonding-curve graduates or legacy LPs through this migrator to seed v2 pools atomically.


# ABIs


# Factory

```json
[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_feeToSetter",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "token0",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "token1",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "pair",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "PairCreated",
    "type": "event"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "INIT_CODE_PAIR_HASH",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "name": "allPairs",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "allPairsLength",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "tokenA",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "tokenB",
        "type": "address"
      }
    ],
    "name": "createPair",
    "outputs": [
      {
        "internalType": "address",
        "name": "pair",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "feeTo",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "feeToSetter",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "getPair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "_feeTo",
        "type": "address"
      }
    ],
    "name": "setFeeTo",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "_feeToSetter",
        "type": "address"
      }
    ],
    "name": "setFeeToSetter",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

```


# Router

```json
[
  {
    "type": "function",
    "name": "factory",
    "inputs": [],
    "outputs": [
      {
        "type": "address",
        "name": ""
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "WETH",
    "inputs": [],
    "outputs": [
      {
        "type": "address",
        "name": ""
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "addLiquidity",
    "inputs": [
      {
        "type": "address",
        "name": "tokenA"
      },
      {
        "type": "address",
        "name": "tokenB"
      },
      {
        "type": "uint256",
        "name": "amountADesired"
      },
      {
        "type": "uint256",
        "name": "amountBDesired"
      },
      {
        "type": "uint256",
        "name": "amountAMin"
      },
      {
        "type": "uint256",
        "name": "amountBMin"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256",
        "name": "amountA"
      },
      {
        "type": "uint256",
        "name": "amountB"
      },
      {
        "type": "uint256",
        "name": "liquidity"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "addLiquidityETH",
    "inputs": [
      {
        "type": "address",
        "name": "token"
      },
      {
        "type": "uint256",
        "name": "amountTokenDesired"
      },
      {
        "type": "uint256",
        "name": "amountTokenMin"
      },
      {
        "type": "uint256",
        "name": "amountETHMin"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256",
        "name": "amountToken"
      },
      {
        "type": "uint256",
        "name": "amountETH"
      },
      {
        "type": "uint256",
        "name": "liquidity"
      }
    ],
    "stateMutability": "payable"
  },
  {
    "type": "function",
    "name": "removeLiquidity",
    "inputs": [
      {
        "type": "address",
        "name": "tokenA"
      },
      {
        "type": "address",
        "name": "tokenB"
      },
      {
        "type": "uint256",
        "name": "liquidity"
      },
      {
        "type": "uint256",
        "name": "amountAMin"
      },
      {
        "type": "uint256",
        "name": "amountBMin"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256",
        "name": "amountA"
      },
      {
        "type": "uint256",
        "name": "amountB"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "removeLiquidityETH",
    "inputs": [
      {
        "type": "address",
        "name": "token"
      },
      {
        "type": "uint256",
        "name": "liquidity"
      },
      {
        "type": "uint256",
        "name": "amountTokenMin"
      },
      {
        "type": "uint256",
        "name": "amountETHMin"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256",
        "name": "amountToken"
      },
      {
        "type": "uint256",
        "name": "amountETH"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "swapExactTokensForTokens",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountIn"
      },
      {
        "type": "uint256",
        "name": "amountOutMin"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "swapExactTokensForTokensSupportingFeeOnTransferTokens",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountIn"
      },
      {
        "type": "uint256",
        "name": "amountOutMin"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "getAmountsOut",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountIn"
      },
      {
        "type": "address[]",
        "name": "path"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getAmountsIn",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountOut"
      },
      {
        "type": "address[]",
        "name": "path"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "swapExactETHForTokens",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountOutMin"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "payable"
  },
  {
    "type": "function",
    "name": "swapExactTokensForETH",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountIn"
      },
      {
        "type": "uint256",
        "name": "amountOutMin"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "swapTokensForExactTokens",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountOut"
      },
      {
        "type": "uint256",
        "name": "amountInMax"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "swapETHForExactTokens",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountOut"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "payable"
  },
  {
    "type": "function",
    "name": "swapTokensForExactETH",
    "inputs": [
      {
        "type": "uint256",
        "name": "amountOut"
      },
      {
        "type": "uint256",
        "name": "amountInMax"
      },
      {
        "type": "address[]",
        "name": "path"
      },
      {
        "type": "address",
        "name": "to"
      },
      {
        "type": "uint256",
        "name": "deadline"
      }
    ],
    "outputs": [
      {
        "type": "uint256[]",
        "name": "amounts"
      }
    ],
    "stateMutability": "nonpayable"
  }
]
```


# Pair

```json
[
  {
    "inputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "Burn",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "name": "Mint",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0In",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1In",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount0Out",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount1Out",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "Swap",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint112",
        "name": "reserve0",
        "type": "uint112"
      },
      {
        "indexed": false,
        "internalType": "uint112",
        "name": "reserve1",
        "type": "uint112"
      }
    ],
    "name": "Sync",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "DOMAIN_SEPARATOR",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "MINIMUM_LIQUIDITY",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "PERMIT_TYPEHASH",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "allowance",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "burn",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amount0",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "factory",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "getReserves",
    "outputs": [
      {
        "internalType": "uint112",
        "name": "_reserve0",
        "type": "uint112"
      },
      {
        "internalType": "uint112",
        "name": "_reserve1",
        "type": "uint112"
      },
      {
        "internalType": "uint32",
        "name": "_blockTimestampLast",
        "type": "uint32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "_token0",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_token1",
        "type": "address"
      }
    ],
    "name": "initialize",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "kLast",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "mint",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "liquidity",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "nonces",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "permit",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "price0CumulativeLast",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "price1CumulativeLast",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      }
    ],
    "name": "skim",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amount0Out",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amount1Out",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "bytes",
        "name": "data",
        "type": "bytes"
      }
    ],
    "name": "swap",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [],
    "name": "sync",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "token0",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "token1",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

```


# Integration Workflows

#### Discovering or Creating Pools

1. Call `factory.getPair(tokenA, tokenB)`.
2. If it returns `address(0)`, call `factory.createPair(tokenA, tokenB)` (tokens will be sorted).
3. Alternatively, derive the address off-chain via `pair = address(uint(keccak256(abi.encodePacked(hex'ff', factory, keccak256(abi.encodePacked(token0, token1)), INIT_CODE_PAIR_HASH))))` and watch for `PairCreated`.

#### Adding Liquidity (token-token)

1. Use `router.getAmountsOut` or `WarpLibrary.quote` to decide `amountAMin`/`amountBMin`.
2. `IERC20(tokenA/B).approve(router, amountADesired/amountBDesired)`.
3. Call `router.addLiquidity(...)` and receive LP tokens in `to`.
4. Capture the returned `(amountA, amountB, liquidity)` for accounting.\
   *For bonding-curve launchpads graduating to Warp, `addLiquidityETH` is typically the final step that pairs the emitted token with native ETH/WMEGAETH.*

#### Removing Liquidity

* Use `removeLiquidity` or `removeLiquidityETH` to withdraw, optionally signing a permit beforehand so the router can transfer LP tokens without a separate transaction.
* Integrations that tax transfers must route through the `SupportingFeeOnTransferTokens` variants to avoid shortfalls.

#### Swapping

1. Construct a `path` array (up to any length) of token addresses.
2. Determine `amountIn`/`amountOut` via the helper methods.
3. Approve the router for the first token (unless swapping from native ETH).
4. Call the appropriate swap function and monitor for `Swap` events emitted by each touched pair.
5. Set `deadline` on every user call to avoid stuck transactions.


# Events & Monitoring

* `WarpFactory.PairCreated(token0, token1, pair, pairIndex)` – emitted once per pool.
* `WarpPair.Mint(sender, amount0, amount1)` – a new liquidity provision.
* `WarpPair.Burn(sender, amount0, amount1, to)` – liquidity withdrawn.
* `WarpPair.Swap(sender, amount0In, amount1In, amount0Out, amount1Out, to)` – emitted on every hop in router swaps.
* `WarpPair.Sync(reserve0, reserve1)` – reserves updated; ingest for analytics/TWAPs.
* ERC-20 `Transfer` on LP tokens – track LP ownership changes.
* Router does not emit custom events; rely on pair-level emissions and transaction logs.


# OLI (Open Labels Initiative)

This document tracks the official OLI attestations and schemas for WarpX.

### 1. WarpX Official Attestations <a href="#user-content-1-warpx-official-attestations" id="user-content-1-warpx-official-attestations"></a>

These are the specific on-chain records that verify WarpX's identity and pools.

#### 🛡️ Label Trust (Attested Jan 2026) <a href="#user-content-label-trust-attested-jan-2026" id="user-content-label-trust-attested-jan-2026"></a>

**Description**: Establishes the WarpX Deployer (`0x0B95...`) as a trusted root entity in the OLI network.

* **UID**: [0x9a16f7cff9033bc67a5c6d09df727a8fba8a03a3ab08a3aae7ad7ca705150092](https://base.easscan.org/attestation/view/0x9a16f7cff9033bc67a5c6d09df727a8fba8a03a3ab08a3aae7ad7ca705150092)
* **Schema Used**: Trust Schema

#### 🏭 Contract Labels (Attested Dec 2025) <a href="#user-content--contract-labels-attested-dec-2025" id="user-content--contract-labels-attested-dec-2025"></a>

**Description**: Labels identifying the V2 Factory and Router contracts.

* **WarpFactory**: [0xf2479c62c865ea8461fbe8abdb97fd17cf1f261db0a3d0752b2dda350f96cace](https://base.easscan.org/attestation/view/0xf2479c62c865ea8461fbe8abdb97fd17cf1f261db0a3d0752b2dda350f96cace)
* **WarpRouter**: [0x3f012bc7dc9a2046e50b6a1aab353a63eb20e75c6c1c0defe0c9e078dd492bec](https://base.easscan.org/attestation/view/0x3f012bc7dc9a2046e50b6a1aab353a63eb20e75c6c1c0defe0c9e078dd492bec)

#### 💧 Pool Labels (Attested Jan 2026) <a href="#user-content--pool-labels-attested-jan-2026" id="user-content--pool-labels-attested-jan-2026"></a>

**Description**: Metadata for WarpX liquidity pools (WETH pairs).

* **WETH/MEKA**: [0x8642f2b586a76ae6e3bfce232c8da957b3a1d2e3db73404073b64bd66df7a256](https://base.easscan.org/attestation/view/0x8642f2b586a76ae6e3bfce232c8da957b3a1d2e3db73404073b64bd66df7a256)
* **WETH/FLUFFEY**: [0x34119f0565b4b1e6ac08cf523477312505c613abc8028d5d0cb5ece66cc6681d](https://base.easscan.org/attestation/view/0x34119f0565b4b1e6ac08cf523477312505c613abc8028d5d0cb5ece66cc6681d)

***

### 2. OLI Base Schemas <a href="#user-content-2-oli-base-schemas" id="user-content-2-oli-base-schemas"></a>

These are the global Schema definitions used to create the attestations above.

#### Trust Schema <a href="#user-content-trust-schema" id="user-content-trust-schema"></a>

**Purpose**: Defines the structure for Trust Tables (owner, attesters, confidence). **Schema UID**: [0x6d780a85bfad501090cd82868a0c773c09beafda609d54888a65c106898c363d](https://base.easscan.org/schema/view/0x6d780a85bfad501090cd82868a0c773c09beafda609d54888a65c106898c363d)

### Important Resources <a href="#user-content-important-resources" id="user-content-important-resources"></a>

* **Official Website**: [openlabelsinitiative.org](https://www.openlabelsinitiative.org/)
* **GitHub Repository**: [github.com/openlabelsinitiative/OLI](https://github.com/openlabelsinitiative/OLI)
* **Python SDK**: [github.com/openlabelsinitiative/oli-python](https://github.com/openlabelsinitiative/oli-python)


# Miniblocks

Real-time blockchain analytics for MegaETH.

WarpX is the first native DEX on megaETH to go live on MegaETH Mainnet! \
You can check the real-time performance at megaeth's very own community-built data site\
<https://miniblocks.io/dapps/warpx>

<figure><img src="https://63028006-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkR1tLrlraBtyo6UB6Vds%2Fuploads%2FK9BJtaRhvJFvz8ooqIeC%2Fimage.png?alt=media&amp;token=03a9e2c1-8da4-4bb2-92bd-3630d404906e" alt=""><figcaption></figcaption></figure>


