diff --git a/src/keywords.json b/src/keywords.json index b3fdb280..a833abdc 100644 --- a/src/keywords.json +++ b/src/keywords.json @@ -39,6 +39,11 @@ "test", "echidna" ], + "/swap": [ + "swap", + "trade", + "swapping" + ], "/super": [ "calling", "parent", diff --git a/src/nav.ts b/src/nav.ts index b5088b15..ccbcb1e0 100644 --- a/src/nav.ts +++ b/src/nav.ts @@ -32,6 +32,10 @@ export const SOL_ROUTES: Route[] = [ path: "create-liquidity", title: "Create Liquidity" }, + { + path: "swap", + title: "Swap" + }, { path: "hello-world", title: "Hello World", diff --git a/src/pages/swap/Swap.sol b/src/pages/swap/Swap.sol new file mode 100644 index 00000000..d5be89f1 --- /dev/null +++ b/src/pages/swap/Swap.sol @@ -0,0 +1,36 @@ +// 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 {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol"; +import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; + +contract Swap { + // set the router address + PoolSwapTest swapRouter = PoolSwapTest(0x01); + + // slippage tolerance to allow for unlimited price impact + uint160 public constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_RATIO + 1; + uint160 public constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_RATIO - 1; + + /// @notice Swap tokens + /// @param key the pool where the swap is happening + /// @param amountSpecified the amount of tokens to swap + /// @param zeroForOne whether the swap is token0 -> token1 or token1 -> token0 + /// @param hookData any data to be passed to the pool's hook + function swap(PoolKey memory key, int256 amountSpecified, bool zeroForOne, bytes memory hookData) internal { + IPoolManager.SwapParams memory params = IPoolManager.SwapParams({ + zeroForOne: zeroForOne, + amountSpecified: amountSpecified, + sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT // unlimited impact + }); + + // in v4, users have the option to receieve native ERC20s or wrapped ERC1155 tokens + // here, we'll take the ERC20s + PoolSwapTest.TestSettings memory testSettings = + PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + + swapRouter.swap(key, params, testSettings, hookData); + } +} diff --git a/src/pages/swap/SwapExampleInputs.sol b/src/pages/swap/SwapExampleInputs.sol new file mode 100644 index 00000000..f8e1d22c --- /dev/null +++ b/src/pages/swap/SwapExampleInputs.sol @@ -0,0 +1,52 @@ +// 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 {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol"; +import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol"; + +contract SwapExampleInputs { + // set the router address + PoolSwapTest swapRouter = PoolSwapTest(0x01); + + // slippage tolerance to allow for unlimited price impact + uint160 public constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_RATIO + 1; + uint160 public constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_RATIO - 1; + + function exampleA() internal { + 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 swap router + IERC20(token0).approve(address(swapRouter), type(uint256).max); + IERC20(token1).approve(address(swapRouter), type(uint256).max); + + // ---------------------------- // + // Swap 1e18 token0 into token1 + // ---------------------------- // + bool zeroForOne = true; + IPoolManager.SwapParams memory params = IPoolManager.SwapParams({ + zeroForOne: zeroForOne, + amountSpecified: 1e18, + sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT // unlimited impact + }); + + // in v4, users have the option to receieve native ERC20s or wrapped ERC1155 tokens + // here, we'll take the ERC20s + PoolSwapTest.TestSettings memory testSettings = + PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true}); + + bytes memory hookData = new bytes(0); // no hook data on the hookless pool + swapRouter.swap(key, params, testSettings, hookData); + } +} diff --git a/src/pages/swap/index.html.ts b/src/pages/swap/index.html.ts new file mode 100644 index 00000000..fc2f6700 --- /dev/null +++ b/src/pages/swap/index.html.ts @@ -0,0 +1,126 @@ +// metadata +export const version = "0.8.20" +export const title = "Single Swap" +export const description = "Swapping on a single pool" + +export const keywords = [ + "swap", + "trade", + "swapping", +] + +export const codes = [ + { + fileName: "Swap.sol", + code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCB7SVBvb2xNYW5hZ2VyfSBmcm9tICJAdW5pc3dhcC92NC1jb3JlL2NvbnRyYWN0cy9pbnRlcmZhY2VzL0lQb29sTWFuYWdlci5zb2wiOwppbXBvcnQge1Bvb2xLZXl9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3R5cGVzL1Bvb2xLZXkuc29sIjsKaW1wb3J0IHtQb29sU3dhcFRlc3R9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3Rlc3QvUG9vbFN3YXBUZXN0LnNvbCI7CmltcG9ydCB7VGlja01hdGh9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL2xpYnJhcmllcy9UaWNrTWF0aC5zb2wiOwoKY29udHJhY3QgU3dhcCB7CiAgICAvLyBzZXQgdGhlIHJvdXRlciBhZGRyZXNzCiAgICBQb29sU3dhcFRlc3Qgc3dhcFJvdXRlciA9IFBvb2xTd2FwVGVzdCgweDAxKTsKCiAgICAvLyBzbGlwcGFnZSB0b2xlcmFuY2UgdG8gYWxsb3cgZm9yIHVubGltaXRlZCBwcmljZSBpbXBhY3QKICAgIHVpbnQxNjAgcHVibGljIGNvbnN0YW50IE1JTl9QUklDRV9MSU1JVCA9IFRpY2tNYXRoLk1JTl9TUVJUX1JBVElPICsgMTsKICAgIHVpbnQxNjAgcHVibGljIGNvbnN0YW50IE1BWF9QUklDRV9MSU1JVCA9IFRpY2tNYXRoLk1BWF9TUVJUX1JBVElPIC0gMTsKCiAgICAvLy8gQG5vdGljZSBTd2FwIHRva2VucwogICAgLy8vIEBwYXJhbSBrZXkgdGhlIHBvb2wgd2hlcmUgdGhlIHN3YXAgaXMgaGFwcGVuaW5nCiAgICAvLy8gQHBhcmFtIGFtb3VudFNwZWNpZmllZCB0aGUgYW1vdW50IG9mIHRva2VucyB0byBzd2FwCiAgICAvLy8gQHBhcmFtIHplcm9Gb3JPbmUgd2hldGhlciB0aGUgc3dhcCBpcyB0b2tlbjAgLT4gdG9rZW4xIG9yIHRva2VuMSAtPiB0b2tlbjAKICAgIC8vLyBAcGFyYW0gaG9va0RhdGEgYW55IGRhdGEgdG8gYmUgcGFzc2VkIHRvIHRoZSBwb29sJ3MgaG9vawogICAgZnVuY3Rpb24gc3dhcChQb29sS2V5IG1lbW9yeSBrZXksIGludDI1NiBhbW91bnRTcGVjaWZpZWQsIGJvb2wgemVyb0Zvck9uZSwgYnl0ZXMgbWVtb3J5IGhvb2tEYXRhKSBpbnRlcm5hbCB7CiAgICAgICAgSVBvb2xNYW5hZ2VyLlN3YXBQYXJhbXMgbWVtb3J5IHBhcmFtcyA9IElQb29sTWFuYWdlci5Td2FwUGFyYW1zKHsKICAgICAgICAgICAgemVyb0Zvck9uZTogemVyb0Zvck9uZSwKICAgICAgICAgICAgYW1vdW50U3BlY2lmaWVkOiBhbW91bnRTcGVjaWZpZWQsCiAgICAgICAgICAgIHNxcnRQcmljZUxpbWl0WDk2OiB6ZXJvRm9yT25lID8gTUlOX1BSSUNFX0xJTUlUIDogTUFYX1BSSUNFX0xJTUlUIC8vIHVubGltaXRlZCBpbXBhY3QKICAgICAgICB9KTsKCiAgICAgICAgLy8gaW4gdjQsIHVzZXJzIGhhdmUgdGhlIG9wdGlvbiB0byByZWNlaWV2ZSBuYXRpdmUgRVJDMjBzIG9yIHdyYXBwZWQgRVJDMTE1NSB0b2tlbnMKICAgICAgICAvLyBoZXJlLCB3ZSdsbCB0YWtlIHRoZSBFUkMyMHMKICAgICAgICBQb29sU3dhcFRlc3QuVGVzdFNldHRpbmdzIG1lbW9yeSB0ZXN0U2V0dGluZ3MgPQogICAgICAgICAgICBQb29sU3dhcFRlc3QuVGVzdFNldHRpbmdzKHt3aXRoZHJhd1Rva2VuczogdHJ1ZSwgc2V0dGxlVXNpbmdUcmFuc2ZlcjogdHJ1ZX0pOwoKICAgICAgICBzd2FwUm91dGVyLnN3YXAoa2V5LCBwYXJhbXMsIHRlc3RTZXR0aW5ncywgaG9va0RhdGEpOwogICAgfQp9Cg==", + }, + { + fileName: "SwapExampleInputs.sol", + code: "Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4yMDsKCmltcG9ydCB7SVBvb2xNYW5hZ2VyfSBmcm9tICJAdW5pc3dhcC92NC1jb3JlL2NvbnRyYWN0cy9pbnRlcmZhY2VzL0lQb29sTWFuYWdlci5zb2wiOwppbXBvcnQge1Bvb2xLZXl9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3R5cGVzL1Bvb2xLZXkuc29sIjsKaW1wb3J0IHtQb29sU3dhcFRlc3R9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL3Rlc3QvUG9vbFN3YXBUZXN0LnNvbCI7CmltcG9ydCB7VGlja01hdGh9IGZyb20gIkB1bmlzd2FwL3Y0LWNvcmUvY29udHJhY3RzL2xpYnJhcmllcy9UaWNrTWF0aC5zb2wiOwoKY29udHJhY3QgU3dhcEV4YW1wbGVJbnB1dHMgewogICAgLy8gc2V0IHRoZSByb3V0ZXIgYWRkcmVzcwogICAgUG9vbFN3YXBUZXN0IHN3YXBSb3V0ZXIgPSBQb29sU3dhcFRlc3QoMHgwMSk7CgogICAgLy8gc2xpcHBhZ2UgdG9sZXJhbmNlIHRvIGFsbG93IGZvciB1bmxpbWl0ZWQgcHJpY2UgaW1wYWN0CiAgICB1aW50MTYwIHB1YmxpYyBjb25zdGFudCBNSU5fUFJJQ0VfTElNSVQgPSBUaWNrTWF0aC5NSU5fU1FSVF9SQVRJTyArIDE7CiAgICB1aW50MTYwIHB1YmxpYyBjb25zdGFudCBNQVhfUFJJQ0VfTElNSVQgPSBUaWNrTWF0aC5NQVhfU1FSVF9SQVRJTyAtIDE7CgogICAgZnVuY3Rpb24gZXhhbXBsZUEoKSBpbnRlcm5hbCB7CiAgICAgICAgYWRkcmVzcyB0b2tlbjAgPSBhZGRyZXNzKDB4MTEpOwogICAgICAgIGFkZHJlc3MgdG9rZW4xID0gYWRkcmVzcygweDIyKTsKCiAgICAgICAgLy8gVXNpbmcgYSBob29rbGVzcyBwb29sCiAgICAgICAgUG9vbEtleSBtZW1vcnkgcG9vbCA9IFBvb2xLZXkoewogICAgICAgICAgICBjdXJyZW5jeTA6IEN1cnJlbmN5KHRva2VuMCksCiAgICAgICAgICAgIGN1cnJlbmN5MTogQ3VycmVuY3kodG9rZW4xKSwKICAgICAgICAgICAgZmVlOiAzMDAwLAogICAgICAgICAgICB0aWNrU3BhY2luZzogNjAsCiAgICAgICAgICAgIGhvb2tzOiBJSG9va3MoYWRkcmVzcygweDApKQogICAgICAgIH0pOwoKICAgICAgICAvLyBhcHByb3ZlIHRva2VucyB0byB0aGUgc3dhcCByb3V0ZXIKICAgICAgICBJRVJDMjAodG9rZW4wKS5hcHByb3ZlKGFkZHJlc3Moc3dhcFJvdXRlciksIHR5cGUodWludDI1NikubWF4KTsKICAgICAgICBJRVJDMjAodG9rZW4xKS5hcHByb3ZlKGFkZHJlc3Moc3dhcFJvdXRlciksIHR5cGUodWludDI1NikubWF4KTsKCiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvLwogICAgICAgIC8vIFN3YXAgMWUxOCB0b2tlbjAgaW50byB0b2tlbjEKICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vCiAgICAgICAgYm9vbCB6ZXJvRm9yT25lID0gdHJ1ZTsKICAgICAgICBJUG9vbE1hbmFnZXIuU3dhcFBhcmFtcyBtZW1vcnkgcGFyYW1zID0gSVBvb2xNYW5hZ2VyLlN3YXBQYXJhbXMoewogICAgICAgICAgICB6ZXJvRm9yT25lOiB6ZXJvRm9yT25lLAogICAgICAgICAgICBhbW91bnRTcGVjaWZpZWQ6IDFlMTgsCiAgICAgICAgICAgIHNxcnRQcmljZUxpbWl0WDk2OiB6ZXJvRm9yT25lID8gTUlOX1BSSUNFX0xJTUlUIDogTUFYX1BSSUNFX0xJTUlUIC8vIHVubGltaXRlZCBpbXBhY3QKICAgICAgICB9KTsKCiAgICAgICAgLy8gaW4gdjQsIHVzZXJzIGhhdmUgdGhlIG9wdGlvbiB0byByZWNlaWV2ZSBuYXRpdmUgRVJDMjBzIG9yIHdyYXBwZWQgRVJDMTE1NSB0b2tlbnMKICAgICAgICAvLyBoZXJlLCB3ZSdsbCB0YWtlIHRoZSBFUkMyMHMKICAgICAgICBQb29sU3dhcFRlc3QuVGVzdFNldHRpbmdzIG1lbW9yeSB0ZXN0U2V0dGluZ3MgPQogICAgICAgICAgICBQb29sU3dhcFRlc3QuVGVzdFNldHRpbmdzKHt3aXRoZHJhd1Rva2VuczogdHJ1ZSwgc2V0dGxlVXNpbmdUcmFuc2ZlcjogdHJ1ZX0pOwoKICAgICAgICBieXRlcyBtZW1vcnkgaG9va0RhdGEgPSBuZXcgYnl0ZXMoMCk7IC8vIG5vIGhvb2sgZGF0YSBvbiB0aGUgaG9va2xlc3MgcG9vbAogICAgICAgIHN3YXBSb3V0ZXIuc3dhcChrZXksIHBhcmFtcywgdGVzdFNldHRpbmdzLCBob29rRGF0YSk7CiAgICB9Cn0K", + }, +] + +const html = `
+

Expect Uniswap Labs to release an official contract around launch

+
+

Using the v4-core provided test router, we can swap on a single pool. These snippets should only be used for non-production, testing purposes

+

Swapping, in production, will typically use a periphery contract. It is not recommended to directly swap with poolManager.swap

+

Swapping will require 3 arguments:

+ +

(Note: A quoter contract is unavailable at this time)

+
// 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 {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol";
+import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol";
+
+contract Swap {
+    // set the router address
+    PoolSwapTest swapRouter = PoolSwapTest(0x01);
+
+    // slippage tolerance to allow for unlimited price impact
+    uint160 public constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_RATIO + 1;
+    uint160 public constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_RATIO - 1;
+
+    /// @notice Swap tokens
+    /// @param key the pool where the swap is happening
+    /// @param amountSpecified the amount of tokens to swap
+    /// @param zeroForOne whether the swap is token0 -> token1 or token1 -> token0
+    /// @param hookData any data to be passed to the pool's hook
+    function swap(PoolKey memory key, int256 amountSpecified, bool zeroForOne, bytes memory hookData) internal {
+        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
+            zeroForOne: zeroForOne,
+            amountSpecified: amountSpecified,
+            sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT // unlimited impact
+        });
+
+        // in v4, users have the option to receieve native ERC20s or wrapped ERC1155 tokens
+        // here, we'll take the ERC20s
+        PoolSwapTest.TestSettings memory testSettings =
+            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true});
+
+        swapRouter.swap(key, params, testSettings, hookData);
+    }
+}
+

Examples of Swapping on a V4 Pool

+
// 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 {PoolSwapTest} from "@uniswap/v4-core/contracts/test/PoolSwapTest.sol";
+import {TickMath} from "@uniswap/v4-core/contracts/libraries/TickMath.sol";
+
+contract SwapExampleInputs {
+    // set the router address
+    PoolSwapTest swapRouter = PoolSwapTest(0x01);
+
+    // slippage tolerance to allow for unlimited price impact
+    uint160 public constant MIN_PRICE_LIMIT = TickMath.MIN_SQRT_RATIO + 1;
+    uint160 public constant MAX_PRICE_LIMIT = TickMath.MAX_SQRT_RATIO - 1;
+
+    function exampleA() internal {
+        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 swap router
+        IERC20(token0).approve(address(swapRouter), type(uint256).max);
+        IERC20(token1).approve(address(swapRouter), type(uint256).max);
+
+        // ---------------------------- //
+        // Swap 1e18 token0 into token1
+        // ---------------------------- //
+        bool zeroForOne = true;
+        IPoolManager.SwapParams memory params = IPoolManager.SwapParams({
+            zeroForOne: zeroForOne,
+            amountSpecified: 1e18,
+            sqrtPriceLimitX96: zeroForOne ? MIN_PRICE_LIMIT : MAX_PRICE_LIMIT // unlimited impact
+        });
+
+        // in v4, users have the option to receieve native ERC20s or wrapped ERC1155 tokens
+        // here, we'll take the ERC20s
+        PoolSwapTest.TestSettings memory testSettings =
+            PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true});
+
+        bytes memory hookData = new bytes(0); // no hook data on the hookless pool
+        swapRouter.swap(key, params, testSettings, hookData);
+    }
+}
+
` + +export default html diff --git a/src/pages/swap/index.md b/src/pages/swap/index.md new file mode 100644 index 00000000..1819ef82 --- /dev/null +++ b/src/pages/swap/index.md @@ -0,0 +1,30 @@ +--- +title: Single Swap +version: 0.8.20 +description: Swapping on a single pool +keywords: [swap, trade, swapping] +--- + +> Expect Uniswap Labs to release an official contract around launch + +Using the `v4-core` provided *test* router, we can swap on a single pool. These snippets should only be used for non-production, testing purposes + +Swapping, in production, will typically use a periphery contract. It is **not** recommended to directly swap with `poolManager.swap` + +Swapping involves 3 primary arguments: + +* Which pool/hook to swap on +* The direction of the swap, token0 -> token1 or token1 -> token0 +* The input token amount + +(Note: A quoter contract is unavailable at this time) + +```solidity +{{{Swap}}} +``` + +### Examples of Swapping on a V4 Pool + +```solidity +{{{SwapExampleInputs}}} +``` diff --git a/src/pages/swap/index.tsx b/src/pages/swap/index.tsx new file mode 100644 index 00000000..e44c294e --- /dev/null +++ b/src/pages/swap/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 3cf11d53..fdb27dcb 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -98,6 +98,7 @@ import component_signature from "./pages/signature" import component_state_variables from "./pages/state-variables" import component_structs from "./pages/structs" import component_super from "./pages/super" +import component_swap from "./pages/swap" import component_tests_echidna from "./pages/tests/echidna" import component_try_catch from "./pages/try-catch" import component_unchecked_math from "./pages/unchecked-math" @@ -523,6 +524,10 @@ const routes: Route[] = [ path: "/super", component: component_super }, + { + path: "/swap", + component: component_swap + }, { path: "/tests/echidna", component: component_tests_echidna diff --git a/src/search.json b/src/search.json index 0b8e6114..935f992f 100644 --- a/src/search.json +++ b/src/search.json @@ -142,6 +142,20 @@ "echidna": [ "/tests/echidna" ], + "swap": [ + "/swap", + "/defi/uniswap-v3-swap", + "/defi/uniswap-v3-flash-swap", + "/defi/uniswap-v2-flash-swap", + "/defi/uniswap-v2", + "/defi/stable-swap-amm" + ], + "trade": [ + "/swap" + ], + "swapping": [ + "/swap" + ], "calling": [ "/super", "/calling-contract" @@ -724,13 +738,6 @@ "/defi/uniswap-v3-flash-swap", "/defi/uniswap-v3-flash" ], - "swap": [ - "/defi/uniswap-v3-swap", - "/defi/uniswap-v3-flash-swap", - "/defi/uniswap-v2-flash-swap", - "/defi/uniswap-v2", - "/defi/stable-swap-amm" - ], "amm": [ "/defi/uniswap-v3-swap", "/defi/uniswap-v3-liquidity",