Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snippets for liquidity creation #2

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/keywords.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,12 @@
"memory",
"calldata"
],
"/create-liquidity": [
"liquidity",
"LP",
"provision",
"supply"
],
"/constructor": [
"constructor",
"constructors",
Expand Down
4 changes: 4 additions & 0 deletions src/nav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const SOL_ROUTES: Route[] = [
path: "initialize",
title: "Pool Initialize"
},
{
path: "create-liquidity",
title: "Create Liquidity"
},
{
path: "hello-world",
title: "Hello World",
Expand Down
26 changes: 26 additions & 0 deletions src/pages/create-liquidity/CreateLiquidity.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol";
import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {PoolModifyPositionTest} from "@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol";

contract CreateLiquidity {
// set the router address
PoolModifyPositionTest lpRouter = PoolModifyPositionTest(0x01);

function createLiquidity(
PoolKey memory poolKey,
int24 tickLower,
int24 tickUpper,
int256 liquidity,
bytes calldata hookData
) external {
// if 0 < liquidity: add liquidity -- otherwise remove liquidity
lpRouter.modifyPosition(
poolKey,
IPoolManager.ModifyPositionParams({tickLower: tickLower, tickUpper: tickUpper, liquidityDelta: liquidity}),
hookData
);
}
}
43 changes: 43 additions & 0 deletions src/pages/create-liquidity/CreateLiquidityExampleInputs.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IERC20} from "forge-std/interfaces/IERC20.sol";
import {IPoolManager} from "@uniswap/v4-core/contracts/interfaces/IPoolManager.sol";
import {PoolKey} from "@uniswap/v4-core/contracts/types/PoolKey.sol";
import {PoolModifyPositionTest} from "@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol";
import {CurrencyLibrary, Currency} from "@uniswap/v4-core/contracts/types/Currency.sol";

contract CreateLiquidityExampleInputs {
using CurrencyLibrary for Currency;

// set the router address
PoolModifyPositionTest lpRouter = PoolModifyPositionTest(0x01);

function exampleA() external {
address token0 = address(0x11);
address token1 = address(0x22);

// Using a hookless pool
PoolKey memory pool = PoolKey({
currency0: Currency(token0),
currency1: Currency(token1),
fee: 3000,
tickSpacing: 60,
hooks: IHooks(address(0x0))
});

// approve tokens to the LP Router
IERC20(token0).approve(address(lpRouter), type(uint256).max);
IERC20(token1).approve(address(lpRouter), type(uint256).max);

// Provide 10e18 worth of liquidity on the range of [-600, 600]
int24 tickLower = -600;
int24 tickUpper = 600;
int256 liquidity = 10e18;
lpRouter.modifyPosition(
poolKey,
IPoolManager.ModifyPositionParams({tickLower: tickLower, tickUpper: tickUpper, liquidityDelta: liquidity}),
new bytes(0)
);
}
}
104 changes: 104 additions & 0 deletions src/pages/create-liquidity/index.html.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// metadata
export const version = "0.8.20"
export const title = "Create Liquidity"
export const description = "Providing Liquidity to a Uniswap V4 Pool"

export const keywords = [
"liquidity",
"LP",
"provision",
"supply",
]

export const codes = [
{
fileName: "CreateLiquidity.sol",
code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCB7SVBvb2xNYW5hZ2VyfSBmcm9tICJAdW5pc3dhcC92NC1jb3JlL2NvbnRyYWN0cy9pbnRlcmZhY2VzL0lQb29sTWFuYWdlci5zb2wiOwppbXBvcnQge1Bvb2xLZXl9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3R5cGVzL1Bvb2xLZXkuc29sIjsKaW1wb3J0IHtQb29sTW9kaWZ5UG9zaXRpb25UZXN0fSBmcm9tICJAdW5pc3dhcC92NC1jb3JlL2NvbnRyYWN0cy90ZXN0L1Bvb2xNb2RpZnlQb3NpdGlvblRlc3Quc29sIjsKCmNvbnRyYWN0IENyZWF0ZUxpcXVpZGl0eSB7CiAgICAvLyBzZXQgdGhlIHJvdXRlciBhZGRyZXNzCiAgICBQb29sTW9kaWZ5UG9zaXRpb25UZXN0IGxwUm91dGVyID0gUG9vbE1vZGlmeVBvc2l0aW9uVGVzdCgweDAxKTsKCiAgICBmdW5jdGlvbiBjcmVhdGVMaXF1aWRpdHkoCiAgICAgICAgUG9vbEtleSBtZW1vcnkgcG9vbEtleSwKICAgICAgICBpbnQyNCB0aWNrTG93ZXIsCiAgICAgICAgaW50MjQgdGlja1VwcGVyLAogICAgICAgIGludDI1NiBsaXF1aWRpdHksCiAgICAgICAgYnl0ZXMgY2FsbGRhdGEgaG9va0RhdGEKICAgICkgZXh0ZXJuYWwgewogICAgICAgIC8vIGlmIDAgPCBsaXF1aWRpdHk6IGFkZCBsaXF1aWRpdHkgLS0gb3RoZXJ3aXNlIHJlbW92ZSBsaXF1aWRpdHkKICAgICAgICBscFJvdXRlci5tb2RpZnlQb3NpdGlvbigKICAgICAgICAgICAgcG9vbEtleSwKICAgICAgICAgICAgSVBvb2xNYW5hZ2VyLk1vZGlmeVBvc2l0aW9uUGFyYW1zKHt0aWNrTG93ZXI6IHRpY2tMb3dlciwgdGlja1VwcGVyOiB0aWNrVXBwZXIsIGxpcXVpZGl0eURlbHRhOiBsaXF1aWRpdHl9KSwKICAgICAgICAgICAgaG9va0RhdGEKICAgICAgICApOwogICAgfQp9Cg==",
},
{
fileName: "CreateLiquidityExampleInputs.sol",
code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCB7SUVSQzIwfSBmcm9tICJmb3JnZS1zdGQvaW50ZXJmYWNlcy9JRVJDMjAuc29sIjsKaW1wb3J0IHtJUG9vbE1hbmFnZXJ9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL2ludGVyZmFjZXMvSVBvb2xNYW5hZ2VyLnNvbCI7CmltcG9ydCB7UG9vbEtleX0gZnJvbSAiQHVuaXN3YXAvdjQtY29yZS9jb250cmFjdHMvdHlwZXMvUG9vbEtleS5zb2wiOwppbXBvcnQge1Bvb2xNb2RpZnlQb3NpdGlvblRlc3R9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3Rlc3QvUG9vbE1vZGlmeVBvc2l0aW9uVGVzdC5zb2wiOwppbXBvcnQge0N1cnJlbmN5TGlicmFyeSwgQ3VycmVuY3l9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3R5cGVzL0N1cnJlbmN5LnNvbCI7Cgpjb250cmFjdCBDcmVhdGVMaXF1aWRpdHlFeGFtcGxlSW5wdXRzIHsKICAgIHVzaW5nIEN1cnJlbmN5TGlicmFyeSBmb3IgQ3VycmVuY3k7CgogICAgLy8gc2V0IHRoZSByb3V0ZXIgYWRkcmVzcwogICAgUG9vbE1vZGlmeVBvc2l0aW9uVGVzdCBscFJvdXRlciA9IFBvb2xNb2RpZnlQb3NpdGlvblRlc3QoMHgwMSk7CgogICAgZnVuY3Rpb24gZXhhbXBsZUEoKSBleHRlcm5hbCB7CiAgICAgICAgYWRkcmVzcyB0b2tlbjAgPSBhZGRyZXNzKDB4MTEpOwogICAgICAgIGFkZHJlc3MgdG9rZW4xID0gYWRkcmVzcygweDIyKTsKCiAgICAgICAgLy8gVXNpbmcgYSBob29rbGVzcyBwb29sCiAgICAgICAgUG9vbEtleSBtZW1vcnkgcG9vbCA9IFBvb2xLZXkoewogICAgICAgICAgICBjdXJyZW5jeTA6IEN1cnJlbmN5KHRva2VuMCksCiAgICAgICAgICAgIGN1cnJlbmN5MTogQ3VycmVuY3kodG9rZW4xKSwKICAgICAgICAgICAgZmVlOiAzMDAwLAogICAgICAgICAgICB0aWNrU3BhY2luZzogNjAsCiAgICAgICAgICAgIGhvb2tzOiBJSG9va3MoYWRkcmVzcygweDApKQogICAgICAgIH0pOwoKICAgICAgICAvLyBhcHByb3ZlIHRva2VucyB0byB0aGUgTFAgUm91dGVyCiAgICAgICAgSUVSQzIwKHRva2VuMCkuYXBwcm92ZShhZGRyZXNzKGxwUm91dGVyKSwgdHlwZSh1aW50MjU2KS5tYXgpOwogICAgICAgIElFUkMyMCh0b2tlbjEpLmFwcHJvdmUoYWRkcmVzcyhscFJvdXRlciksIHR5cGUodWludDI1NikubWF4KTsKCiAgICAgICAgLy8gUHJvdmlkZSAxMGUxOCB3b3J0aCBvZiBsaXF1aWRpdHkgb24gdGhlIHJhbmdlIG9mIFstNjAwLCA2MDBdCiAgICAgICAgaW50MjQgdGlja0xvd2VyID0gLTYwMDsKICAgICAgICBpbnQyNCB0aWNrVXBwZXIgPSA2MDA7CiAgICAgICAgaW50MjU2IGxpcXVpZGl0eSA9IDEwZTE4OwogICAgICAgIGxwUm91dGVyLm1vZGlmeVBvc2l0aW9uKAogICAgICAgICAgICBwb29sS2V5LAogICAgICAgICAgICBJUG9vbE1hbmFnZXIuTW9kaWZ5UG9zaXRpb25QYXJhbXMoe3RpY2tMb3dlcjogdGlja0xvd2VyLCB0aWNrVXBwZXI6IHRpY2tVcHBlciwgbGlxdWlkaXR5RGVsdGE6IGxpcXVpZGl0eX0pLAogICAgICAgICAgICBuZXcgYnl0ZXMoMCkKICAgICAgICApOwogICAgfQp9Cg==",
},
]

const html = `<blockquote>
<p>Expect Uniswap Labs to release an official contract around launch</p>
</blockquote>
<blockquote>
<p>⚠️ Using the test router in production will lead to a loss of funds ⚠️ </p>
</blockquote>
<p>Using the <code>v4-core</code> provided <em>test</em> router, we can provide liquidity to a pool. This should only be used for non-production testing purposes</p>
<p>Creating liquidity involves using periphery contracts. It is <strong>not</strong> recommended to directly provide liquidity with <code>poolManager.modifyPosition</code></p>
<pre><code class="language-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">IPoolManager</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">PoolKey</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/types/PoolKey.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">PoolModifyPositionTest</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CreateLiquidity</span> </span>{
<span class="hljs-comment">// set the router address</span>
PoolModifyPositionTest lpRouter <span class="hljs-operator">=</span> PoolModifyPositionTest(<span class="hljs-number">0x01</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createLiquidity</span>(<span class="hljs-params">
PoolKey <span class="hljs-keyword">memory</span> poolKey,
<span class="hljs-keyword">int24</span> tickLower,
<span class="hljs-keyword">int24</span> tickUpper,
<span class="hljs-keyword">int256</span> liquidity,
<span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> hookData
</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
<span class="hljs-comment">// if 0 &lt; liquidity: add liquidity -- otherwise remove liquidity</span>
lpRouter.modifyPosition(
poolKey,
IPoolManager.ModifyPositionParams({tickLower: tickLower, tickUpper: tickUpper, liquidityDelta: liquidity}),
hookData
);
}
}
</code></pre><h3>Examples of Providing Liquidity to a V4 Pool</h3>
<pre><code class="language-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">IERC20</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"forge-std/interfaces/IERC20.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IPoolManager</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/interfaces/IPoolManager.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">PoolKey</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/types/PoolKey.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">PoolModifyPositionTest</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/test/PoolModifyPositionTest.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">CurrencyLibrary</span>, <span class="hljs-title">Currency</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@uniswap/v4-core/contracts/types/Currency.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CreateLiquidityExampleInputs</span> </span>{
<span class="hljs-keyword">using</span> <span class="hljs-title">CurrencyLibrary</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">Currency</span>;

<span class="hljs-comment">// set the router address</span>
PoolModifyPositionTest lpRouter <span class="hljs-operator">=</span> PoolModifyPositionTest(<span class="hljs-number">0x01</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">exampleA</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
<span class="hljs-keyword">address</span> token0 <span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0x11</span>);
<span class="hljs-keyword">address</span> token1 <span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0x22</span>);

<span class="hljs-comment">// Using a hookless pool</span>
PoolKey <span class="hljs-keyword">memory</span> pool <span class="hljs-operator">=</span> PoolKey({
currency0: Currency(token0),
currency1: Currency(token1),
fee: <span class="hljs-number">3000</span>,
tickSpacing: <span class="hljs-number">60</span>,
hooks: IHooks(<span class="hljs-keyword">address</span>(<span class="hljs-number">0x0</span>))
});

<span class="hljs-comment">// approve tokens to the LP Router</span>
IERC20(token0).approve(<span class="hljs-keyword">address</span>(lpRouter), <span class="hljs-keyword">type</span>(<span class="hljs-keyword">uint256</span>).<span class="hljs-built_in">max</span>);
IERC20(token1).approve(<span class="hljs-keyword">address</span>(lpRouter), <span class="hljs-keyword">type</span>(<span class="hljs-keyword">uint256</span>).<span class="hljs-built_in">max</span>);

<span class="hljs-comment">// Provide 10e18 worth of liquidity on the range of [-600, 600]</span>
<span class="hljs-keyword">int24</span> tickLower <span class="hljs-operator">=</span> <span class="hljs-number">-600</span>;
<span class="hljs-keyword">int24</span> tickUpper <span class="hljs-operator">=</span> <span class="hljs-number">600</span>;
<span class="hljs-keyword">int256</span> liquidity <span class="hljs-operator">=</span> <span class="hljs-number">10e18</span>;
lpRouter.modifyPosition(
poolKey,
IPoolManager.ModifyPositionParams({tickLower: tickLower, tickUpper: tickUpper, liquidityDelta: liquidity}),
<span class="hljs-keyword">new</span> <span class="hljs-keyword">bytes</span>(<span class="hljs-number">0</span>)
);
}
}
</code></pre>`

export default html
27 changes: 27 additions & 0 deletions src/pages/create-liquidity/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: Create Liquidity
version: 0.8.20
description: Providing Liquidity to a Uniswap V4 Pool
keywords: [liquidity, LP, provision, supply]
---

> Expect Uniswap Labs to release an official contract around launch

> ⚠️ Using the test router in production will lead to a loss of funds ⚠️

Using the `v4-core` provided *test* router, we can provide liquidity to a pool. This should only be used for non-production testing purposes




Creating liquidity involves using periphery contracts. It is **not** recommended to directly provide liquidity with `poolManager.modifyPosition`

```solidity
{{{CreateLiquidity}}}
```

### Examples of Providing Liquidity to a V4 Pool

```solidity
{{{CreateLiquidityExampleInputs}}}
```
29 changes: 29 additions & 0 deletions src/pages/create-liquidity/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react"
import Example from "../../components/Example"
import html, { version, title, description, codes } from "./index.html"

interface Path {
path: string
title: string
}

interface Props {
prev: Path | null
next: Path | null
}

const ExamplePage: React.FC<Props> = ({ prev, next }) => {
return (
<Example
version={version}
title={title}
description={description}
html={html}
prev={prev}
next={next}
codes={codes}
/>
)
}

export default ExamplePage
5 changes: 5 additions & 0 deletions src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import component_call from "./pages/call"
import component_calling_contract from "./pages/calling-contract"
import component_constants from "./pages/constants"
import component_constructor from "./pages/constructor"
import component_create_liquidity from "./pages/create-liquidity"
import component_data_locations from "./pages/data-locations"
import component_defi_chainlink_price_oracle from "./pages/defi/chainlink-price-oracle"
import component_defi_constant_product_amm from "./pages/defi/constant-product-amm"
Expand Down Expand Up @@ -266,6 +267,10 @@ const routes: Route[] = [
path: "/constructor",
component: component_constructor
},
{
path: "/create-liquidity",
component: component_create_liquidity
},
{
path: "/data-locations",
component: component_data_locations
Expand Down
12 changes: 10 additions & 2 deletions src/search.json
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,8 @@
],
"liquidity": [
"/defi/uniswap-v3-liquidity",
"/defi/uniswap-v2-add-remove-liquidity"
"/defi/uniswap-v2-add-remove-liquidity",
"/create-liquidity"
],
"arbitrage": [
"/defi/uniswap-v3-flash-swap"
Expand Down Expand Up @@ -774,7 +775,8 @@
"/defi/uniswap-v2-optimal-one-sided-supply"
],
"supply": [
"/defi/uniswap-v2-optimal-one-sided-supply"
"/defi/uniswap-v2-optimal-one-sided-supply",
"/create-liquidity"
],
"add": [
"/defi/uniswap-v2-add-remove-liquidity",
Expand Down Expand Up @@ -834,6 +836,12 @@
"calldata": [
"/data-locations"
],
"LP": [
"/create-liquidity"
],
"provision": [
"/create-liquidity"
],
"constructor": [
"/constructor"
],
Expand Down
Loading