flashloan-rs 0.2.1

Minimal Multicall3 Flashloan Module
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
/// @title FixedPointMath
/// @notice Fixed-point number arithmetic
///         Original implementation:
///         https://github.com/transmissions11/solmate/blob/v7/src/utils/FixedPointMathLib.sol
/// @author solmate <https://github.com/transmissions11/solmate>
/// @author clabby <https://github.com/clabby>
/// @author Maddiaa <https://github.com/cheethas>

#define constant WAD = 0x0de0b6b3a7640000
#define constant DAY = 0x15180

#define macro TO_WAD_UNSAFE() = takes (1) returns (1) {
    [WAD] mul
}

#define macro toDaysWadUnsafe() = takes (1) returns (1) {
    [WAD] mul [DAY] div
}


#define macro FROM_DAYS_WAD_UNSAFE() = takes (1) returns (1) {
    [DAY] mul [WAD] div
}


#define macro UNSAFE_WAD_MUL() = takes (2) returns (1) {
    mul [WAD] sdiv
}


#define macro UNSAFE_WAD_DIV() = takes (2) returns (1) {
    // Input Stack: [x, y]
    [WAD] mul                  // [(x * 1e18), y]
    sdiv
}

#define macro UNSAFE_DIV() = takes(2) returns(1) {
    sdiv
}

// wadMul(int256 x, int256 y) pure returns (int256)
#define macro WAD_MUL(fail) = takes(2) returns(1) {
                      // [x,y]

    dup2 dup2         // [x,y,x,y]
    mul               // [[x*y] (r),x,y]

    dup2              // [x,r,x,y]
    dup2              // [r,x,r,x,y]
    sdiv              // [(r/x),r,x,y]
    dup4              // [y,(r/x),r,x,y]
    eq                // [y==(r/x),r,x,y]

    dup3              // [x,y==(r/x),r,x,y]
    iszero            // [iszero(0), y==(r/x),r,x,y]
    or                // [iszero(0) || y==(r/x) ,r,x,y]
    iszero            // [iszero(iszero(0) || y==(r/x)),r,x,y]
    <fail> jumpi

    // [r,x,y]
    [WAD]
    swap1
    sdiv            // [r,x,y]

    // clean stack
    swap2 pop pop   // [r]
}


#define macro WAD_DIV(fail) = takes(2) returns(1) {
                        // [x,y]
    dup1                // [x,x,y]
    [WAD] dup1          // [w,w,x,x,y]
    swap2               // [x,w,w,x,y]

    mul                 // [r,w,x,y]
    dup1                // [r,r,w,x,y]
    swap2               // [w,r,r,x,y]
    swap1               // [r,w,r,x,y]

    sdiv                // [r/w,r,x,y]
    dup3                // [x,r/w,r,x,y]
    eq                  // [x==(r/w),r,x,y]

    dup4                // [y,x==(r/w),r,x,y]
    iszero              // [iszero(y),x==(r/w),r,x,y]
    iszero              // [!iszero(y) && x==(r/w),r,x,y]
    and                 // [iszero(y) && x==(r/w),r,x,y]
    iszero              // [iszero(iszero(y) && x==(r/w)),r,x,y]
    <fail> jumpi

    // [r,x,y]
    swap1             // [x,r,y]
    pop               // [r,y]
    sdiv              // [r/y]
}


// https://github.com/transmissions11/solmate/blob/v7/src/utils/FixedPointMathLib.sol#L34
#define macro EXP_WAD(fail) = takes (1) returns (1) {
    // Input stack:            [x]

    // When the result is < 0.5 we return zero. This happens when
    // x <= floor(log(0.5e18) * 1e18) ~ -42e18
    0xfffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1
    dup2                    // [x, 0xfff..., x]
    sgt iszero              // [x <= 0xfff..., x]
    ret_zero jumpi          // [x]

    // When the result is > (2**255 - 1) / 1e18 we can not represent it as an
    // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.
    0x0755bf798b4a1bf1e5    // [0x0755bf798b4a1bf1e5, x]
    dup2                    // [x, 0x0755bf798b4a1bf1e5, x]
    slt iszero              // [x >= 0x0755bf798b4a1bf1e5, x]
    <fail> jumpi            // [x]

    // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96
    // for more intermediate precision and a binary basis. This base conversion
    // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.
    0x03782dace9d9          // [0x05 ** 0x12, x]
    swap1                   // [x, 0x05 ** 0x12]
    0x4e shl                // [x << 0x4e, 0x05 ** 0x12]
    sdiv                    // [x << 0x4e / 0x05 ** 0x12]

    // Reduce range of x to (-1/2 ln 2, 1/2 ln 2) * 2**96 by factoring out powers
    // of two such that exp(x) = exp(x') * 2**k, where k is an integer.
    // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).
    0xb17217f7d1cf79abc9e3b398
    dup2                    // [x, 0xb17217f7d1cf79abc9e3b398, x]
    0x60 shl                // [x << 96, 0xb17217f7d1cf79abc9e3b398, x]
    sdiv                    // [x << 96 / 0xb17217f7d1cf79abc9e3b398, x]
    0x7ffffff20f9306d2eea00000 // [2**95, x << 96 / 0xb17217f7d1cf79abc9e3b398, x]
    add                     // [2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398, x]
    0x60 sar                // [(2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96, x]

    dup1                    // [(2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96, (2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96, x]
    0xb17217f7d1cf79abc9e3b398
    mul                     // [((2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96) * 0xb17217f7d1cf79abc9e3b398, (2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96, x]
    dup3                    // [x, ((2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96) * 0xb17217f7d1cf79abc9e3b398, (2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96, x]
    sub                     // [x (new), (2**95 + x << 96 / 0xb17217f7d1cf79abc9e3b398) >> 96, x]
    swap2 pop               // [k, x]

    // k is in the range [-61, 195].

    // Evaluate using a (6, 7)-term rational approximation.
    // p is made monic, we'll multiply by a scale factor later.
    0x10fe68e7fd37d0007b713f7650
    dup3                    // [x, 0x10fe68e7fd37d0007b713f7650, k, x]
    add                     // [y, k, x]

    0x02d16720577bd19bf614176fe9ea
    dup2 dup5 mul           // [x * y, 0x02d16720577bd19bf614176fe9ea, y, k, x]
    0x60 sar                // [(x * y) >> 0x60, 0x02d16720577bd19bf614176fe9ea, y, k, x]
    add                     // [((x * y) >> 0x60) + 0x02d16720577bd19bf614176fe9ea, y, k, x]
    swap1 pop               // [y, k, x]

    0x04a4fd9f2a8b96949216d2255a6c
    dup4 dup3 add           // [x + y, 0x04a4fd9f2a8b96949216d2255a6c, y, k, x]
    sub                     // [x + y - 0x04a4fd9f2a8b96949216d2255a6c, y, k, x]

    dup2                    // [y, x + y - 0x04a4fd9f2a8b96949216d2255a6c, y, k, x]
    mul                     // [y * (x + y - 0x04a4fd9f2a8b96949216d2255a6c), y, k, x]
    0x60 sar                // [(y * (x + y - 0x04a4fd9f2a8b96949216d2255a6c)) >> 0x60, y, k, x]
    0x0587f503bb6ea29d25fcb740196450
    add                     // [p, y, k, x]

    dup4                    // [x, p, y, k, x]
    mul                     // [x * p, y, k, x]
    0xd835ebba824c98fb31b83b2ca45c
    0x60 shl                // [0xd835ebba824c98fb31b83b2ca45c << 0x60, x * p, y, k, x]
    add                     // [p, y, k, x]

    // We leave p in 2**192 basis so we don't need to scale it back up for the division.

    0x240c330e9fb2d9cbaf0fd5aafc
    dup5 sub                // [q, p, y, k, x]

    dup5 mul                // [x * q, p, y, k, x]
    0x60 sar                // [(x * q) >> 0x60, p, y, k, x]
    0x0277594991cfc85f6e2461837cd9
    add                     // [q, p, y, k, x]

    dup5 mul                // [x * q, p, y, k, x]
    0x60 sar                // [(x * q) >> 0x60, p, y, k, x]
    0x1a521255e34f6a5061b25ef1c9c4 swap1
    sub                     // [q, p, y, k, x]

    dup5 mul                // [x * q, p, y, k, x]
    0x60 sar                // [(x * q) >> 0x60, p, y, k, x]
    0xb1bbb201f443cf962f1a1d3db4a5
    add                     // [q, p, y, k, x]

    dup5 mul                // [x * q, p, y, k, x]
    0x60 sar                // [(x * q) >> 0x60, p, y, k, x]
    0x02c72388d9f74f51a9331fed693f15 swap1
    sub                     // [q, p, y, k, x]

    dup5 mul                // [x * q, p, y, k, x]
    0x60 sar                // [(x * q) >> 0x60, p, y, k, x]
    0x05180bb14799ab47a8a8cb2a527d57
    add                     // [q, p, y, k, x]

    // The q polynomial won't have zeros in the domain as all its roots are complex.
    // No scaling is necessary because p is already 2**96 too large.
    swap1 sdiv              // [p / q (r), y, k, x]

    // r should be in the range (0.09, 0.25) * 2**96.

    // We now need to multiply r by:
    // * the scale factor s = ~6.031367120.
    // * the 2**k factor from the range reduction.
    // * the 1e18 / 2**96 factor for base conversion.
    // We do this all at once, with an intermediate result in 2**213
    // basis, so the final right shift is always by a positive amount.

    0x029d9dc38563c32e5c2f6dc192ee70ef65f9978af3
    mul                     // [0x029d9... * r, y, k, x]
    dup3                    // [k, 0x029d9... * r, y, k, x]
    0xc3 sub                // [0xc3 - k, 0x029d9... * r, y, k, x]
    shr                     // [(0x029d9... * r) >> 0xc3 - k, y, k, x]

    // Clean stack
    swap3 pop pop pop       // [result]

    finish jump

    ret_zero:
        0x00 dup1 mstore
        0x20 0x00 return
    finish:
    // Return stack:           [result]
}

// https://github.com/transmissions11/solmate/blob/v7/src/utils/FixedPointMathLib.sol#L92
#define macro LN_WAD(fail) = takes (1) returns (1) {
    // Input stack:            [x]
    0x00 dup2 sgt           // [x > 0, x]
    iszero                  // [x <= 0, x]
    <fail> jumpi              // [x]

    // We want to convert x from 10**18 fixed point to 2**96 fixed point.
    // We do this by multiplying by 2**96 / 10**18. But since
    // ln(x * C) = ln(x) + ln(C), we can simply do nothing here
    // and add ln(2**96 / 10**18) at the end.

    // Reduce range of x to (1, 2) * 2**96
    // ln(2^k * x) = k * ln(2) + ln(x)
    0x60                    // [0x60, x]
    dup2 LOG_2(fail)        // [log2(x), 0x60, x]
    sub                     // [k, x]

    dup2 dup2               // [k, x, k, x]
    0x9f sub                // [0x9f - k, x, k, x]
    shl                     // [x << (0x9f - k), k, x]
    0x9f shr                // [x_new, k, x]
    swap2 pop               // [k, x]

    // Evaluate using a (8, 8)-term rational approximation.
    // p is made monic, we will multiply by a scale factor later.
    dup2                    // [x, k, x]
    0x29508e458543d8aa4df2abee78
    add                     // [p, k, x]

    dup3 mul                // [p * x, k, x]
    0x60 sar                // [(p * x) >> 0x60, k, x]
    0x0139601a2efabe717e604cbb4894
    add                     // [p, k, x]

    dup3 mul                // [p * x, k, x]
    0x60 sar                // [(p * x) >> 0x60, k, x]
    0x02247f7a7b6594320649aa03aba1
    add                     // [p, k, x]

    0x8c3f38e95a6b1ff2ab1c3b3437
    swap1 dup4 mul          // [p * x, 0x8c3f..., k, x]
    0x60 sar                // [(p * x) >> 0x60, 0x8c3f..., k, x]
    sub                     // [p, k, x]

    0x02384773bdf1ac5676facced6091
    swap1 dup4 mul          // [p * x, 0x0238..., k, x]
    0x60 sar                // [(p * x) >> 0x60, 0x0238..., k, x]
    sub                     // [p, k, x]

    0xb9a025d814b29c212b8b1a07ce
    swap1 dup4 mul          // [p * x, 0xb9a0..., k, x]
    0x60 sar                // [(p * x) >> 0x60, 0xb9a0..., k, x]
    sub                     // [p, k, x]

    0x0a09507084cc699bb0e71ea86a
    0x60 shl                // [0x0a09... << 0x60, p, k, x]
    swap1                   // [p, 0x0a09... << 0x60, k, x]
    dup4 mul                // [p * x, 0x0a09... << 0x60, k, x]
    sub                     // [p, k, x]

    // We leave p in 2**192 basis so we don't need to scale it back up for the division.
    // q is monic by convention.
    dup3                    // [x, p, k, x]
    0x465772b2bbbb5f824b15207a30
    add                     // [q, p, k, x]

    dup4 mul                // [q * x, p, k, x]
    0x60 sar                // [(q * x) >> 0x60, p, k, x]
    0x0388eaa27412d5aca026815d636e
    add                     // [q, p, k, x]

    dup4 mul                // [q * x, p, k, x]
    0x60 sar                // [(q * x) >> 0x60, p, k, x]
    0x0df99ac502031bf953eff472fdcc
    add                     // [q, p, k, x]

    dup4 mul                // [q * x, p, k, x]
    0x60 sar                // [(q * x) >> 0x60, p, k, x]
    0x13cdffb29d51d99322bdff5f2211
    add                     // [q, p, k, x]

    dup4 mul                // [q * x, p, k, x]
    0x60 shr                // [(q * x) >> 0x60, p, k, x]
    0x0a0f742023def783a307a986912e
    add                     // [q, p, k, x]

    dup4 mul                // [q * x, p, k, x]
    0x60 sar                // [(q * x) >> 0x60, p, k, x]
    0x01920d8043ca89b5239253284e42
    add                     // [q, p, k, x]

    dup4 mul                // [q * x, p, k, x]
    0x60 sar                // [(q * x) >> 0x60, p, k, x]
    0x0b7a86d7375468fac667a0a527
    add                     // [q, p, k, x]

    // The q polynomial is known not to have zeros in the domain.
    // No scaling required because p is already 2**96 too large.
    swap1 sdiv              // [p / q (r), k, x]

    // r is in the range (0, 0.125) * 2**96

    // Finalization, we need to:
    // * multiply by the scale factor s = 5.549...
    // * add ln(2**96 / 10**18)
    // * add k * ln(2)
    // * multiply by 10**18 / 2**96 = 5**18 >> 78

    // mul s * 5e18 * 2**96, base is now 5**18 * 2**192
    0x1340daa0d5f769dba1915cef59f0815a5506 mul

    // add ln(2) * k * 5e18 * 2**192
    swap1                   // [k, r, x]
    0x0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b3
    mul                     // [k * 0x0267..., r, x]
    add                     // [r, x]

    // add ln(2**96 / 10**18) * 5e18 * 2**192
    0x57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b8864284
    add                     // [r, x]

    // base conversion: mul 2**18 / 2**192
    0xAE sar                // [r >> 0xAE, x]

    finish jump

    finish:
        // Clean stack
        swap1 pop
    // Return stack:           [result]
}

// https://github.com/transmissions11/solmate/blob/v7/src/utils/FixedPointMathLib.sol#L29
#define macro POW_WAD(fail) = takes (2) returns (1) {
    // Input Stack:            [x, y]
    LN_WAD(fail)                // [lnWad(x), y]
    mul                     // [lnWad(x) * y]
    [WAD] swap1             // [lnWad(x) * y, 1e18]
    sdiv                    // [(lnWad(x) * y) / 1e18]
    EXP_WAD(fail)               // [result]
}


// https://github.com/transmissions11/solmate/blob/v7/src/utils/FixedPointMathLib.sol#L352
#define macro LOG_2(fail) = takes (1) returns (1) {
    // Input stack:                [x]

    dup1 iszero                 // [x == 0, x]
    <fail> jumpi                // [x]

    dup1                        // [x, x]
    0xffffffffffffffffffffffffffffffff
    lt                          // [0xffff... < x, x]
    0x07 shl                    // [r, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0xffffffffffffffff lt       // [0xffff... < (x >> r), r, x]
    0x06 shl                    // [(0xffff... < (x >> r)) << 6, r, x]
    or                          // [r | (0xffff... < (x >> r)) << 6, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0xffffffff lt               // [0xffff... < (x >> r), r, x]
    0x05 shl                    // [(0xffff... < (x >> r)) << 5, r, x]
    or                          // [r | (0xffff... < (x >> r)) << 5, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0xffff lt                   // [0xffff < (x >> r), r, x]
    0x04 shl                    // [(0xffff < (x >> r)) << 4, r, x]
    or                          // [r | (0xffff < (x >> r)) << 4, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0xff lt                     // [0xff < (x >> r), r, x]
    0x03 shl                    // [(0xff < (x >> r)) << 3, r, x]
    or                          // [r | (0xff < (x >> r)) << 3, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0x0f lt                     // [0x0f < (x >> r), r, x]
    0x02 shl                    // [(0x0f < (x >> r)) << 2, r, x]
    or                          // [r | (0x0f < (x >> r)) << 2, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0x03 lt                     // [0x03 < (x >> r), r, x]
    0x01 shl                    // [(0x03 < (x >> r)) << 1, r, x]
    or                          // [r | (0x03 < (x >> r)) << 1, x]

    dup2 dup2                   // [r, x, r, x]
    shr                         // [x >> r, r, x]
    0x01 lt                     // [0x01 < (x >> r), r, x]
    or                          // [r, x]
    swap1 pop                   // [r]

    // Return stack:            // [result]
}