From bfc7f36dd032104e3a2a8b540c6a5c1f2dff3205 Mon Sep 17 00:00:00 2001 From: saucepoint Date: Wed, 18 Oct 2023 14:39:47 -0400 Subject: [PATCH] snippets for liquidity creation --- src/keywords.json | 6 + src/nav.ts | 4 + .../create-liquidity/CreateLiquidity.sol | 26 +++++ .../CreateLiquidityExampleInputs.sol | 43 ++++++++ src/pages/create-liquidity/index.html.ts | 104 ++++++++++++++++++ src/pages/create-liquidity/index.md | 27 +++++ src/pages/create-liquidity/index.tsx | 29 +++++ src/routes.tsx | 5 + src/search.json | 12 +- 9 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 src/pages/create-liquidity/CreateLiquidity.sol create mode 100644 src/pages/create-liquidity/CreateLiquidityExampleInputs.sol create mode 100644 src/pages/create-liquidity/index.html.ts create mode 100644 src/pages/create-liquidity/index.md create mode 100644 src/pages/create-liquidity/index.tsx diff --git a/src/keywords.json b/src/keywords.json index 9847884e3..b3fdb280b 100644 --- a/src/keywords.json +++ b/src/keywords.json @@ -501,6 +501,12 @@ "memory", "calldata" ], + "/create-liquidity": [ + "liquidity", + "LP", + "provision", + "supply" + ], "/constructor": [ "constructor", "constructors", diff --git a/src/nav.ts b/src/nav.ts index d4ba04a1f..b5088b156 100644 --- a/src/nav.ts +++ b/src/nav.ts @@ -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", diff --git a/src/pages/create-liquidity/CreateLiquidity.sol b/src/pages/create-liquidity/CreateLiquidity.sol new file mode 100644 index 000000000..8648eaa47 --- /dev/null +++ b/src/pages/create-liquidity/CreateLiquidity.sol @@ -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 + ); + } +} diff --git a/src/pages/create-liquidity/CreateLiquidityExampleInputs.sol b/src/pages/create-liquidity/CreateLiquidityExampleInputs.sol new file mode 100644 index 000000000..0416ac1f7 --- /dev/null +++ b/src/pages/create-liquidity/CreateLiquidityExampleInputs.sol @@ -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) + ); + } +} diff --git a/src/pages/create-liquidity/index.html.ts b/src/pages/create-liquidity/index.html.ts new file mode 100644 index 000000000..5c6ccd312 --- /dev/null +++ b/src/pages/create-liquidity/index.html.ts @@ -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 = `
+

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

+
// 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
+        );
+    }
+}
+

Examples of Providing Liquidity to a V4 Pool

+
// 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)
+        );
+    }
+}
+
` + +export default html diff --git a/src/pages/create-liquidity/index.md b/src/pages/create-liquidity/index.md new file mode 100644 index 000000000..21b7794ba --- /dev/null +++ b/src/pages/create-liquidity/index.md @@ -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}}} +``` diff --git a/src/pages/create-liquidity/index.tsx b/src/pages/create-liquidity/index.tsx new file mode 100644 index 000000000..e44c294e3 --- /dev/null +++ b/src/pages/create-liquidity/index.tsx @@ -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 = ({ prev, next }) => { + return ( + + ) +} + +export default ExamplePage diff --git a/src/routes.tsx b/src/routes.tsx index bf049794c..3cf11d536 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -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" @@ -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 diff --git a/src/search.json b/src/search.json index 6e6493b22..0b8e61149 100644 --- a/src/search.json +++ b/src/search.json @@ -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" @@ -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", @@ -834,6 +836,12 @@ "calldata": [ "/data-locations" ], + "LP": [ + "/create-liquidity" + ], + "provision": [ + "/create-liquidity" + ], "constructor": [ "/constructor" ],