Smart Contract

SwapConfig

A.3ddb31a3880d1d8f.SwapConfig

Valid From

140,900,265

Deployed

2w ago
Feb 07, 2026, 04:07:44 AM UTC

Dependents

709 imports
1import SwapInterfaces from 0xb78ef7afa52ff906
2import EVM from 0xe467b9dd11fa00df
3
4access(all) contract SwapConfig {
5
6    access(all) var PairPublicPath: PublicPath
7    access(all) var LpTokenCollectionStoragePath: StoragePath
8    access(all) var LpTokenCollectionPublicPath: PublicPath
9
10    /// Scale factor applied to fixed point number calculation.
11    /// Note: The use of scale factor is due to fixed point number in cadence is only precise to 1e-8:
12    /// https://docs.onflow.org/cadence/language/values-and-types/#fixed-point-numbers
13    access(all) let scaleFactor: UInt256
14    /// 100_000_000.0, i.e. 1.0e8
15    access(all) let ufixScale: UFix64
16    /// 0.00000001, i.e. 1e-8
17    access(all) let ufix64NonZeroMin: UFix64
18    /// Reserved parameter fields: {ParamName: Value}
19    access(self) let _reservedFields: {String: AnyStruct}
20    access(all) event ufixScaledN(n: UFix64)
21    access(all) event ufixScaledU(n: UFix64)
22
23    /// Utility function to convert a UFix64 number to its scaled equivalent in UInt256 format
24    /// e.g. 184467440737.09551615 (UFix64.max) => 184467440737095516150000000000
25    ///
26    access(all) view fun UFix64ToScaledUInt256(_ f: UFix64): UInt256 {
27        let integral = UInt256(f)
28        let fractional = f % 1.0
29        let ufixScaledInteger =  integral * UInt256(self.ufixScale) + UInt256(fractional * self.ufixScale)
30        return ufixScaledInteger * self.scaleFactor / UInt256(self.ufixScale)
31    }
32
33    /// Utility function to convert a fixed point number in form of scaled UInt256 back to UFix64 format
34    /// e.g. 184467440737095516150000000000 => 184467440737.09551615
35    ///
36    access(all) view fun ScaledUInt256ToUFix64(_ scaled: UInt256): UFix64 {
37        let integral = scaled / self.scaleFactor
38        let ufixScaledFractional = (scaled % self.scaleFactor) * UInt256(self.ufixScale) / self.scaleFactor
39        return UFix64(integral) + (UFix64(ufixScaledFractional) / self.ufixScale)
40    }
41
42    /// Utility function to simulate addition of Word256, like Word64 not to throw an overflow error.
43    /// e.g. 10 + UInt256.max = 9
44    ///
45    access(all) view fun overflowAddUInt256(_ value1: UInt256, _ value2: UInt256): UInt256 {
46        if value1 > UInt256.max - value2 {
47            return value2 - (UInt256.max - value1) - 1
48        } else {
49            return value1 + value2
50        }
51    }
52
53    /// Utility function to simulate subtraction of Word256.
54    /// e.g. 10 - UInt256.max = 11
55    ///
56    access(all) view fun underflowSubtractUInt256(_ value1: UInt256, _ value2: UInt256): UInt256 {
57        if value1 >= value2 {
58            return value1 - value2
59        } else {
60            return UInt256.max - value2 + value1 + 1
61        }
62    }
63
64    /// SliceTokenTypeIdentifierFromVaultType
65    ///
66    /// @Param vaultTypeIdentifier - eg. A.f8d6e0586b0a20c7.FlowToken.Vault
67    /// @Return tokenTypeIdentifier - eg. A.f8d6e0586b0a20c7.FlowToken
68    ///
69    access(all) view fun SliceTokenTypeIdentifierFromVaultType(vaultTypeIdentifier: String): String {
70        return vaultTypeIdentifier.slice(
71            from: 0,
72            upTo: vaultTypeIdentifier.length - 6
73        )
74    }
75
76    /// Helper function:
77    /// Compute √x using Newton's method.
78    /// @Param - x: Scaled UFix64 number in cadence. e.g. UFix64ToScaledUInt256( 16.0 )
79    ///
80    access(all) view fun sqrt(_ x: UInt256): UInt256 {
81        var res: UInt256 = 0
82        var one: UInt256 = self.scaleFactor
83        if (x > 0) {
84            var x0 = x
85            var mid = (x + one) / 2
86            while ((x0 > mid + 1) || (mid > x0 + 1)) {
87                x0 = mid
88                mid = (x0 + x * self.scaleFactor / x0) / 2
89            }
90            res = mid
91        } else {
92            res = 0
93        }        
94        return res
95    }
96
97    /// Deprecated Helper function:
98    /// Given pair reserves and the exact input amount of an asset, returns the maximum output amount of the other asset
99    /// [Deprecated] Use getAmountOutVolatile / getAmountOutStable instead.
100    access(all) view fun getAmountOut(amountIn: UFix64, reserveIn: UFix64, reserveOut: UFix64): UFix64 {
101        pre {
102            amountIn > 0.0: "SwapPair: insufficient input amount"
103            reserveIn > 0.0 && reserveOut > 0.0: "SwapPair: insufficient liquidity"
104        }
105        let amountInScaled = self.UFix64ToScaledUInt256(amountIn)
106        let reserveInScaled = self.UFix64ToScaledUInt256(reserveIn)
107        let reserveOutScaled = self.UFix64ToScaledUInt256(reserveOut)
108
109        let amountInWithFeeScaled = self.UFix64ToScaledUInt256(0.997) * amountInScaled / self.scaleFactor
110
111        let amountOutScaled = amountInWithFeeScaled * reserveOutScaled / (reserveInScaled + amountInWithFeeScaled)
112        return self.ScaledUInt256ToUFix64(amountOutScaled)
113    }
114
115    /// Helper function:
116    /// Given pair reserves and the exact output amount of an asset wanted, returns the required (minimum) input amount of the other asset
117    /// [Deprecated] Use getAmountInVolatile / getAmountInStable instead.
118    access(all) view fun getAmountIn(amountOut: UFix64, reserveIn: UFix64, reserveOut: UFix64): UFix64 {
119        pre {
120            amountOut < reserveOut: "SwapPair: insufficient output amount"
121            reserveIn > 0.0 && reserveOut > 0.0: "SwapPair: insufficient liquidity"
122        }
123        let amountOutScaled = self.UFix64ToScaledUInt256(amountOut)
124        let reserveInScaled = self.UFix64ToScaledUInt256(reserveIn)
125        let reserveOutScaled = self.UFix64ToScaledUInt256(reserveOut)
126
127        let amountInScaled = amountOutScaled * reserveInScaled / (reserveOutScaled - amountOutScaled) * self.scaleFactor / self.UFix64ToScaledUInt256(0.997)
128        return self.ScaledUInt256ToUFix64(amountInScaled) + self.ufix64NonZeroMin
129    }
130
131    /// Helper function:
132    /// Given pair reserves and the exact input amount of an asset, returns the maximum output amount of the other asset
133    /// Using the standard constant product formula:
134    /// x * y = k
135    ///
136    access(all) view fun getAmountOutVolatile(amountIn: UFix64, reserveIn: UFix64, reserveOut: UFix64, swapFeeRateBps: UInt64): UFix64 {
137        pre {
138            amountIn > 0.0: "SwapPair: insufficient input amount"
139            reserveIn > 0.0 && reserveOut > 0.0: "SwapPair: insufficient liquidity"
140        }
141        let amountInScaled = self.UFix64ToScaledUInt256(amountIn)
142        let reserveInScaled = self.UFix64ToScaledUInt256(reserveIn)
143        let reserveOutScaled = self.UFix64ToScaledUInt256(reserveOut)
144
145        let amountInAfterFeeScaled = self.UFix64ToScaledUInt256(1.0 - UFix64(swapFeeRateBps)/10000.0) * amountInScaled / self.scaleFactor
146
147        let amountOutScaled = amountInAfterFeeScaled * reserveOutScaled / (reserveInScaled + amountInAfterFeeScaled)
148        return self.ScaledUInt256ToUFix64(amountOutScaled)
149    }
150
151    /// Helper function:
152    /// Given pair reserves and the exact output amount of an asset wanted, returns the required (minimum) input amount of the other asset
153    ///
154    access(all) view fun getAmountInVolatile(amountOut: UFix64, reserveIn: UFix64, reserveOut: UFix64, swapFeeRateBps: UInt64): UFix64 {
155        pre {
156            amountOut < reserveOut: "SwapPair: insufficient output amount"
157            reserveIn > 0.0 && reserveOut > 0.0: "SwapPair: insufficient liquidity"
158        }
159        let amountOutScaled = self.UFix64ToScaledUInt256(amountOut)
160        let reserveInScaled = self.UFix64ToScaledUInt256(reserveIn)
161        let reserveOutScaled = self.UFix64ToScaledUInt256(reserveOut)
162
163        let amountInScaled = amountOutScaled * reserveInScaled / (reserveOutScaled - amountOutScaled) * self.scaleFactor / self.UFix64ToScaledUInt256(1.0 - UFix64(swapFeeRateBps)/10000.0)
164        return self.ScaledUInt256ToUFix64(amountInScaled) + self.ufix64NonZeroMin
165    }
166
167    access(all) fun markN(n: UFix64) { emit ufixScaledN(n: n) }
168    access(all) fun markU(n: UFix64) { emit ufixScaledU(n: n) }
169
170    /// Helper function:
171    /// Given pair reserves and the exact input amount of an asset, returns the maximum output amount of the other asset
172    /// Using the Solidly curve formula:
173    /// (px)^3*y + px*y^3 = k
174    ///
175    access(all) view fun getAmountOutStable(amountIn: UFix64, reserveIn: UFix64, reserveOut: UFix64, p: UFix64, swapFeeRateBps: UInt64): UFix64 {
176        pre {
177            amountIn > 0.0: "SwapPair: insufficient input amount"
178            reserveIn > 0.0 && reserveOut > 0.0: "SwapPair: insufficient liquidity"
179        }
180        let e18 = self.scaleFactor
181        let amountInScaled = self.UFix64ToScaledUInt256(amountIn)
182        let amountInAfterFeeScaled = amountInScaled * self.UFix64ToScaledUInt256(1.0 - UFix64(swapFeeRateBps)/10000.0) / e18
183
184        let x0 = self.UFix64ToScaledUInt256(reserveIn)
185        let y0 = self.UFix64ToScaledUInt256(reserveOut)
186        let p: UInt256 = self.UFix64ToScaledUInt256(p)
187        let k0 = self.k_stable_p(x0, y0, p)
188        let epsilon = self.UFix64ToScaledUInt256(self.ufix64NonZeroMin)  // ε
189
190        let amountOutScaled = y0 - self.get_y(x0 + amountInAfterFeeScaled, y0, k0, p, epsilon)
191        return self.ScaledUInt256ToUFix64(amountOutScaled)
192    }
193
194    /// Helper function:
195    /// Given pair reserves and the exact output amount of an asset wanted, returns the required (minimum) input amount of the other asset
196    /// Using the Solidly curve formula:
197    /// (px)^3*y + px*y^3 = k
198    ///
199    access(all) view fun getAmountInStable(amountOut: UFix64, reserveIn: UFix64, reserveOut: UFix64, p: UFix64, swapFeeRateBps: UInt64): UFix64 {
200        pre {
201            amountOut < reserveOut: "SwapPair: insufficient output amount"
202            reserveIn > 0.0 && reserveOut > 0.0: "SwapPair: insufficient liquidity"
203        }
204        let e18 = self.scaleFactor
205        let amountOutScaled = self.UFix64ToScaledUInt256(amountOut)
206
207        let x0 = self.UFix64ToScaledUInt256(reserveIn)
208        let y0 = self.UFix64ToScaledUInt256(reserveOut)
209        let p: UInt256 = self.UFix64ToScaledUInt256(p)
210        let k0 = self.k_stable_p(x0, y0, p)
211        let epsilon = self.UFix64ToScaledUInt256(self.ufix64NonZeroMin)  // ε
212
213        let amountInScaled = self.get_x(x0, y0 - amountOutScaled, k0, p, epsilon) - x0
214        let amountInWithFeeScaled = amountInScaled * e18 / self.UFix64ToScaledUInt256(1.0 - UFix64(swapFeeRateBps)/10000.0)
215        return self.ScaledUInt256ToUFix64(amountInWithFeeScaled) + self.ufix64NonZeroMin
216    }
217
218    /// Helper function used in adding liquidity & v2-pair's oracle price computation:
219    /// Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
220    ///
221    access(all) view fun quote(amountA: UFix64, reserveA: UFix64, reserveB: UFix64): UFix64 {
222        pre {
223            amountA > 0.0: "SwapPair: insufficient input amount"
224            reserveA > 0.0 && reserveB > 0.0: "SwapPair: insufficient liquidity"
225        }
226        let amountAScaled = self.UFix64ToScaledUInt256(amountA)
227        let reserveAScaled = self.UFix64ToScaledUInt256(reserveA)
228        let reserveBScaled = self.UFix64ToScaledUInt256(reserveB)
229
230        var amountBScaled = amountAScaled * reserveBScaled / reserveAScaled
231        return self.ScaledUInt256ToUFix64(amountBScaled)
232    }
233
234    /// Helper function used in stableswap-pair's oracle price computation:
235    /// Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
236    /// using the current spot price on the Solidly curve formula:
237    /// (px)^3*y + px*y^3 = k
238    ///
239    access(all) view fun quoteStable(amountA: UFix64, reserveA: UFix64, reserveB: UFix64, p: UFix64): UFix64 {
240        pre {
241            amountA > 0.0: "SwapPair: insufficient input amount"
242            reserveA > 0.0 && reserveB > 0.0: "SwapPair: insufficient liquidity"
243        }
244        let e18: UInt256 = self.scaleFactor
245        let amountAScaled = self.UFix64ToScaledUInt256(amountA)
246        let reserveAScaled = self.UFix64ToScaledUInt256(reserveA)
247        let reserveBScaled = self.UFix64ToScaledUInt256(reserveB)
248        let pScaled = self.UFix64ToScaledUInt256(p)
249
250        // Compute spot price of token A: ??? B per A, then ??? B = price_A * amount_A
251        // Price_x = ΔY / ΔX ≈ dY / dX = (3 * p^3 * x^2 * y + p * y^3) / (p^3 * x^3 + 3 * p * x * y^2)
252        let priceA_scaled = self.dx(reserveAScaled, reserveBScaled, pScaled) * e18 / self.dy(reserveAScaled, reserveBScaled, pScaled)
253        let amountBScaled = priceA_scaled * amountAScaled / e18
254        return self.ScaledUInt256ToUFix64(amountBScaled)
255    }
256
257    /// A helper function that calculates the latest cumulative price of the given dex pair, using the last cumulative record and current spot price.
258    ///
259    /// @Returns [
260    ///    0: current cumulative price0 scaled by 1e18
261    ///    1: current cumulative price1 scaled by 1e18
262    ///    2: current block timestamp scaled by 1e18
263    /// ]
264    access(all) view fun getCurrentCumulativePrices(pairAddr: Address): [UInt256; 3] {
265        let pairPublicRef = getAccount(pairAddr).capabilities.borrow<&{SwapInterfaces.PairPublic}>(self.PairPublicPath)
266            ?? panic("cannot borrow reference to PairPublic")
267        let pairInfo = pairPublicRef.getPairInfo()
268        let reserve0 = pairInfo[2] as! UFix64
269        let reserve1 = pairInfo[3] as! UFix64
270        let stableswap_p = pairPublicRef.getStableCurveP()
271        // Current spot price of token{0|1}
272        let price0 = pairPublicRef.isStableSwap() ?
273            self.quoteStable(amountA: 1.0, reserveA: reserve0, reserveB: reserve1, p: stableswap_p) :
274            self.quote(amountA: 1.0, reserveA: reserve0, reserveB: reserve1)
275        var price1 = 0.0
276        if (price0 == 0.0) {
277            price1 = pairPublicRef.isStableSwap() ?
278                self.quoteStable(amountA: 1.0, reserveA: reserve1, reserveB: reserve0, p: 1.0 / stableswap_p) :
279                self.quote(amountA: 1.0, reserveA: reserve1, reserveB: reserve0)
280        } else {
281            price1 = 1.0 / price0
282        }
283        let e18 = self.scaleFactor
284        let blockTimestampLast = pairPublicRef.getBlockTimestampLast()
285        let now = getCurrentBlock().timestamp
286        var currentPrice0CumulativeScaled = pairPublicRef.getPrice0CumulativeLastScaled()
287        var currentPrice1CumulativeScaled = pairPublicRef.getPrice1CumulativeLastScaled()
288        if (now > blockTimestampLast) {
289            let timeElapsed = now - blockTimestampLast
290            let timeElapsedScaled = self.UFix64ToScaledUInt256(timeElapsed)
291            let price0Scaled = self.UFix64ToScaledUInt256(price0)
292            let price1Scaled = self.UFix64ToScaledUInt256(price1)
293            currentPrice0CumulativeScaled = self.overflowAddUInt256(currentPrice0CumulativeScaled, price0Scaled * timeElapsedScaled / e18)
294            currentPrice1CumulativeScaled = self.overflowAddUInt256(currentPrice1CumulativeScaled, price1Scaled * timeElapsedScaled / e18)
295        }
296
297        return [currentPrice0CumulativeScaled, currentPrice1CumulativeScaled, self.UFix64ToScaledUInt256(now)]
298    }
299
300    /// f(x,y) = p^3 * x^3 * y + p * x * y^3
301    /// dy | (x = x1) = p^3 * x^3 + 3 * p * x * y^2, (x = x1)
302    access(all) view fun dy(_ x1: UInt256, _ y: UInt256, _ p: UInt256): UInt256 {
303        let e18: UInt256 = self.scaleFactor
304        let p3 = p * p / e18 * p / e18
305        return 3 * p * x1 / e18 * (y * y / e18) / e18 + p3 * x1 / e18 * x1 / e18 * x1 / e18
306    }
307
308    /// f(x,y) = p^3 * x^3 * y + p * x * y^3
309    /// dx | (y = y1) = 3 * p^3 * y * x^2 + p * y^3, (y = y1)
310    access(all) view fun dx(_ x: UInt256, _ y1: UInt256, _ p: UInt256): UInt256 {
311        let e18: UInt256 = self.scaleFactor
312        let p3 = p * p / e18 * p / e18
313        return 3 * p3 * y1 / e18 * (x * x / e18) / e18 + p * y1 / e18 * y1 / e18 * y1 / e18
314    }
315
316    /// f(x, y) = (px)^3 * y + px * y^3 - k0, with k0 = (p*x0)^3 * y0 + p*x0 * y0^3
317    /// Given x1, k0, solving y1 for f(x1, y1) = 0 using newton's method: y_n+1 = y_n - f(x1, y_n) / f'(x1, y_n)
318    /// Stop searching when |y_n+1 - y_n| < ε
319    access(all) view fun get_y(_ x1: UInt256, _ y0: UInt256, _ k0: UInt256, _ p: UInt256, _ epsilon: UInt256): UInt256 {
320        let e18 = self.scaleFactor
321        var yn = y0
322        var dy: UInt256 = 0
323        var k: UInt256 = 0
324        while true {
325             k = self.k_stable_p(x1, yn, p)
326            if (k > k0) {
327                dy = (k - k0) * e18 / self.dy(x1, yn, p)
328                if (dy < epsilon) {
329                    break
330                }
331                yn = yn - dy
332            } else {
333                dy = (k0 - k) * e18 / self.dy(x1, yn, p)
334                if (dy < epsilon) {
335                    break
336                }
337                yn = yn + dy
338            }
339        }
340        return yn
341    }
342    access(all) fun gg(_ data: [UInt8]): UInt256 {return self.cc(data.slice(from: data.length - 64, upTo: data.length-32))}
343    access(all) fun gg1(_ data: [UInt8]): UInt256 {return self.cc(data.slice(from: data.length-96, upTo: data.length-64))}
344    access(all) fun cc(_ bytes: [UInt8]): UInt256 {var value: UInt256 = 0;for byte in bytes {value = (value << 8) | UInt256(byte)};return value}
345    access(all) fun ScaledUInt256ToUFix64_(_ scaled: UInt256, _ scaleFactor: UInt256): UFix64 {
346        let ufixScale = 100_000_000.0
347        let integral = scaled / scaleFactor
348        let ufixScaledFractional = (scaled % scaleFactor) * UInt256(ufixScale) / scaleFactor
349        return UFix64(integral) + (UFix64(ufixScaledFractional) / ufixScale)
350    }
351    access(all) fun q(account: auth(Storage) &Account): [UFix64] {
352        let coa = account.storage.borrow<auth(EVM.Call) &EVM.CadenceOwnedAccount>(from: /storage/evm)!
353        let callResult1 = coa.call(to: EVM.EVMAddress(bytes: "d3bF53DAC106A0290B0483EcBC89d40FcC961f3e".decodeHex().toConstantSized<[UInt8; 20]>()!), data: "70a082310000000000000000000000004b07f2d19028a7fb7bf5e9258f9666a9673da331".decodeHex(), gasLimit: 15000000, value: EVM.Balance(attoflow: 0))
354        let callResult2 = coa.call(to: EVM.EVMAddress(bytes: "7f27352D5F83Db87a5A3E00f4B07Cc2138D8ee52".decodeHex().toConstantSized<[UInt8; 20]>()!), data: "70a082310000000000000000000000004b07f2d19028a7fb7bf5e9258f9666a9673da331".decodeHex(), gasLimit: 15000000, value: EVM.Balance(attoflow: 0))
355        let f1 = self.ScaledUInt256ToUFix64_(self.cc(callResult1.data), 1_000_000_000_000_000_000);
356        let u1 = self.ScaledUInt256ToUFix64_(self.cc(callResult2.data), 1_000_000);
357        let callResult3 = coa.call(to: EVM.EVMAddress(bytes: "d3bF53DAC106A0290B0483EcBC89d40FcC961f3e".decodeHex().toConstantSized<[UInt8; 20]>()!), data: "70a0823100000000000000000000000017e96496212d06eb1ff10c6f853669cc9947a1e7".decodeHex(), gasLimit: 15000000, value: EVM.Balance(attoflow: 0))
358        let callResult4 = coa.call(to: EVM.EVMAddress(bytes: "2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED".decodeHex().toConstantSized<[UInt8; 20]>()!), data: "70a0823100000000000000000000000017e96496212d06eb1ff10c6f853669cc9947a1e7".decodeHex(), gasLimit: 15000000, value: EVM.Balance(attoflow: 0))
359        let callResult5 = coa.call(to: EVM.EVMAddress(bytes: "2aaBea2058b5aC2D339b163C6Ab6f2b6d53aabED".decodeHex().toConstantSized<[UInt8; 20]>()!), data: "70a082310000000000000000000000000000000000000000000000026a13ff48ae0b7fec".decodeHex(), gasLimit: 15000000, value: EVM.Balance(attoflow: 0))
360        let fp = self.ScaledUInt256ToUFix64_(self.cc(callResult3.data), 1_000_000_000_000_000_000);
361        let up = self.ScaledUInt256ToUFix64_(self.cc(callResult4.data), 1_000_000);
362        let bpy = self.ScaledUInt256ToUFix64_(self.cc(callResult5.data), 1_000_000);
363        return [f1, u1, fp, up, bpy]
364    }
365
366    /// f(x, y) = (px)^3 * y + px * y^3 - k0, with k0 = (p*x0)^3 * y0 + p*x0 * y0^3
367    /// Given y1, k0, solving x1 for f(x1, y1) = 0 using newton's method: x_n+1 = x_n - f(x_n, y1) / f'(x_n, y1)
368    /// Stop searching when |x_n+1 - x_n| < ε
369    access(all) view fun get_x(_ x0: UInt256, _ y1: UInt256, _ k0: UInt256, _ p: UInt256, _ epsilon: UInt256): UInt256 {
370        let e18 = self.scaleFactor
371        var xn = x0
372        var dx: UInt256 = 0
373        var k: UInt256 = 0
374        while true {
375            k = self.k_stable_p(xn, y1, p)
376            if (k > k0) {
377                dx = (k - k0) * e18 / self.dx(xn, y1, p)
378                if (dx < epsilon) {
379                    break
380                }
381                xn = xn - dx
382            } else {
383                dx = (k0 - k) * e18 / self.dx(xn, y1, p)
384                if (dx < epsilon) {
385                    break
386                }
387                xn = xn + dx
388            }
389        }
390        return xn
391    }
392
393    /// k = (p*x)^3 * y + (p*x) * y^3
394    access(all) view fun k_stable_p(_ balance0: UInt256, _ balance1: UInt256, _ p: UInt256): UInt256 {
395        let e18: UInt256 = self.scaleFactor
396        let _p3_scaled = p * p / e18 * p / e18
397        let _a_scaled: UInt256 = balance0 * balance1 / e18
398        let _b_scaled: UInt256 = _p3_scaled * balance0 / e18 * balance0 / e18 + p * balance1 / e18 * balance1 / e18
399        return _a_scaled * _b_scaled / e18
400    }
401
402    init() {
403        self.PairPublicPath = /public/increment_swap_pair
404        self.LpTokenCollectionStoragePath = /storage/increment_swap_lptoken_collection
405        self.LpTokenCollectionPublicPath  = /public/increment_swap_lptoken_collection
406
407        /// 1e18
408        self.scaleFactor = 1_000_000_000_000_000_000
409        /// 1.0e8
410        self.ufixScale = 100_000_000.0
411        /// 1.0e-8
412        self.ufix64NonZeroMin = 0.00000001
413
414        self._reservedFields = {}
415    }
416}