You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Revise create-pool guide with detailed methods and tips
Updated the create-pool guide to enhance clarity and detail on pool creation methods, including atomic creation with liquidity and best practices for initializing pools without liquidity. Added security considerations and gas optimization benefits.
In this example we will use **ethers.js** and the **Uniswap v4 SDK** to create pools on Uniswap v4. Uniswap v4 is a popular destination for creating markets due to its:
10
10
11
-
- Proven track record and battle-tested codebase
12
-
- Concentrated liquidity, unlocks capital efficiency
13
-
- Flexible pool design through dynamic fees and hooks
14
-
- Gas-efficient architecture
11
+
- Proven track record and battle-tested codebase (over $2.75 trillion in cumulative volume)
12
+
- Concentrated liquidity, unlocking capital efficiency
13
+
- Flexible pool design through dynamic fees and hooks (150+ hooks already developed)
14
+
- Gas-efficient singleton architecture (99.99% cheaper pool creation)
15
+
- Native ETH support without wrapping
16
+
- Flash accounting system for optimized transactions
15
17
- Integrations with alternative trading venues
16
18
17
19
For more information, developers should see [Uniswap v4 Overview](/contracts/v4/overview)
@@ -21,16 +23,20 @@ For this guide, the following Uniswap packages are used:
To initialize a Uniswap v4 Pool _without initial liquidity_, developers should call [`PoolManager.initialize()`](/contracts/v4/concepts/PoolManager)
28
+
Uniswap v4 offers two methods for creating pools:
27
29
28
-
Creating a pool without liquidity may be useful for "reserving" a pool for future use, when initial liquidity is not available, or when external market makers would provide the starting liquidity.
30
+
1.**Initialize pool without liquidity** - Using `PoolManager.initialize()`
31
+
2.**Atomic pool creation with liquidity** - Using `PositionManager` with multicall (recommended)
32
+
33
+
## Recommended: Atomic Pool Creation with Initial Liquidity
34
+
35
+
**Uniswap v4's PositionManager supports atomic creation of a pool and initial liquidity using multicall.** Developers can create a trading pool with liquidity in a single transaction. This is the recommended approach as it avoids the security risks of empty pools.
29
36
30
37
### Configure the Pool
31
38
32
39
We will first create an example configuration `CurrentConfig` in `config.ts`. It has the format:
> For native token pairs (Ether), use `ADDRESS_ZERO` as `currency0`
58
+
> For native token pairs (Ether), use `CurrencyLibrary.ADDRESS_ZERO` as `currency0`
53
59
54
60
[PoolKey](/contracts/v4/reference/core/types/PoolKey) uniquely identifies a pool
55
61
56
62
-_Currencies_ should be sorted, `uint160(currency0) < uint160(currency1)`
57
63
-_lpFee_ is the fee expressed in pips, i.e. 3000 = 0.30%
58
64
-_tickSpacing_ is the granularity of the pool. Lower values are more precise but may be more expensive to trade on
59
-
-_hookContract_ is the address of the hook contract
65
+
-_hookContract_ is the address of the hook contract (use zero address if no hooks)
60
66
61
67
A note on `tickSpacing`:
62
68
63
69
Lower tick spacing provides improved price precision; however, smaller tick spaces will cause swaps to cross ticks more often, incurring higher gas costs.
Math.floor(Date.now() /1000) +60// 60 second deadline
112
+
)
113
+
```
69
114
115
+
- the _startingPrice_ is expressed as sqrtPriceX96: `floor(sqrt(token1 / token0) * 2^96)`
116
+
- i.e. `79228162514264337593543950336` is the starting price for a 1:1 pool
117
+
118
+
## Alternative: Initialize Pool Without Liquidity
119
+
120
+
To initialize a Uniswap v4 Pool _without initial liquidity_, developers should call [`PoolManager.initialize()`](/contracts/v4/concepts/PoolManager)
121
+
122
+
Creating a pool without liquidity may be useful for "reserving" a pool for future use, when initial liquidity is not available, or when external market makers would provide the starting liquidity.
123
+
124
+
### Call `initialize` of Pool Manager contract
70
125
```typescript
71
126
import { ethers } from'ethers'
72
-
const POOL_MANAGER_ADDRESS ='0x000000000004444c5dc75cB358380D2e3dE08A90'//Replace with actual StateView contract address
const POOL_MANAGER_ABI = [...]; // Import or define the ABI for PoolManager contract
74
129
75
130
const provider =getProvider() // Provide the right RPC address for the chain
@@ -84,29 +139,53 @@ const poolManager = new ethers.Contract(
84
139
We get the `POOL_MANAGER_ADDRESS` for our chain from [Uniswap Deployments](/contracts/v4/deployments).
85
140
86
141
Pools are initialized with a starting price
87
-
88
142
```typescript
89
143
const result =awaitpoolManager.initialize(
90
144
CurrentConfig.poolKey,
91
145
startingPrice
92
146
)
93
147
```
94
148
95
-
- the _startingPrice_ is expressed as sqrtPriceX96: `floor(sqrt(token1 / token0) * 2^96)`
96
-
- i.e. `79228162514264337593543950336` is the starting price for a 1:1 pool
97
-
98
149
Now the pool is initialized and you can add liquidity to it.
99
150
100
-
## Important Note on Initial Liquidity
151
+
## Important Security Considerations
152
+
153
+
### Risks of Empty Pools
101
154
102
-
When creating a new pool, it's critical to understand that initializing a pool without liquidity can be dangerous. An empty pool's spot price is freely manipulatable since there is no liquidity to resist price movements.
155
+
When creating a new pool, it's **critical** to understand that initializing a pool without liquidity can be dangerous. An empty pool's spot price is freely manipulatable since there is no liquidity to resist price movements.
103
156
104
157
This means that on the first liquidity provision, if proper slippage parameters are not set:
105
158
106
159
1. Malicious actors can manipulate the price before the first position is minted
107
160
2. The first position can be mispriced and have incorrect asset ratios
161
+
3. Front-running attacks can extract value from the initial LP
162
+
163
+
### Best Practices for Safe Pool Creation
164
+
165
+
**Strongly Recommended:**
166
+
- Use the atomic pool creation method with PositionManager (shown above) to create pool + liquidity in one transaction
167
+
- This eliminates the window for price manipulation attacks
168
+
169
+
**If you must initialize without liquidity:**
170
+
- Add liquidity immediately after pool creation in the same transaction block
171
+
- Always use strict slippage parameters when minting the first position
172
+
- Set appropriate `amount0Max` and `amount1Max` limits
173
+
- Consider using a private mempool or flashbots to prevent front-running
174
+
- Monitor the pool state before adding liquidity
175
+
176
+
Reference our [Mint Position guide](/sdk/v4/guides/liquidity/position-minting) for proper liquidity addition practices.
177
+
178
+
## Gas Optimization Benefits
179
+
180
+
Uniswap v4's singleton architecture provides significant gas savings:
181
+
-**Pool creation**: Up to 99.99% cheaper than v3 (state update vs contract deployment)
182
+
-**Multi-hop swaps**: No intermediate token transfers needed
183
+
-**Flash accounting**: Only net balances settled via EIP-1153 transient storage
184
+
-**Native ETH**: ~15% gas savings on ETH pairs (no wrapping/unwrapping)
108
185
109
-
To safely add the first liquidity to a new pool:
186
+
## Additional Resources
110
187
111
-
- Always use appropriate slippage parameters when minting the first position
112
-
- Consider adding liquidity immediately after pool creation in the same transaction. Reference our [Mint Position guide](/sdk/v4/guides/liquidity/position-minting) for proper liquidity addition practices.
0 commit comments