Smart Contract
SwapConfig
A.3ddb31a3880d1d8f.SwapConfig
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}