├── ReadMe.md
├── Test.sol
├── backend
├── .gitignore
├── package-lock.json
├── package.json
└── src
│ ├── UniswapV2_V3.js
│ ├── abi
│ ├── arbitrage.json
│ ├── erc20.json
│ ├── flashloan.json
│ ├── pancakeswapFactory.json
│ ├── pancakeswapPair.json
│ ├── pancakeswapRouter.json
│ ├── sushiswapV2Factory.json
│ ├── uniswapV2Pair.json
│ └── uniswapV2Router.json
│ ├── app.js
│ ├── config.json
│ ├── pancakeswap.js
│ └── sushiswap.js
├── frontend
└── index.js
└── smartcontract
├── .gitignore
├── contracts
├── FlashloanArbitrage.sol
└── NormalArbitrage.sol
├── hardhat.config.js
├── package-lock.json
├── package.json
├── scripts
├── deployFlashLoan.js
└── deployNormal.js
└── test
└── FlashloanArbitrage.test.js
/ReadMe.md:
--------------------------------------------------------------------------------
1 | # Test Arbitrage Bot
2 |
--------------------------------------------------------------------------------
/Test.sol:
--------------------------------------------------------------------------------
1 | /**
2 | *Submitted for verification at BscScan.com on 2020-09-24
3 | */
4 |
5 | // File: contracts/interfaces/IPancakePair.sol
6 |
7 | pragma solidity >=0.5.0;
8 |
9 | interface IPancakePair {
10 | event Approval(address indexed owner, address indexed spender, uint value);
11 | event Transfer(address indexed from, address indexed to, uint value);
12 |
13 | function name() external pure returns (string memory);
14 | function symbol() external pure returns (string memory);
15 | function decimals() external pure returns (uint8);
16 | function totalSupply() external view returns (uint);
17 | function balanceOf(address owner) external view returns (uint);
18 | function allowance(address owner, address spender) external view returns (uint);
19 |
20 | function approve(address spender, uint value) external returns (bool);
21 | function transfer(address to, uint value) external returns (bool);
22 | function transferFrom(address from, address to, uint value) external returns (bool);
23 |
24 | function DOMAIN_SEPARATOR() external view returns (bytes32);
25 | function PERMIT_TYPEHASH() external pure returns (bytes32);
26 | function nonces(address owner) external view returns (uint);
27 |
28 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
29 |
30 | event Mint(address indexed sender, uint amount0, uint amount1);
31 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
32 | event Swap(
33 | address indexed sender,
34 | uint amount0In,
35 | uint amount1In,
36 | uint amount0Out,
37 | uint amount1Out,
38 | address indexed to
39 | );
40 | event Sync(uint112 reserve0, uint112 reserve1);
41 |
42 | function MINIMUM_LIQUIDITY() external pure returns (uint);
43 | function factory() external view returns (address);
44 | function token0() external view returns (address);
45 | function token1() external view returns (address);
46 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
47 | function price0CumulativeLast() external view returns (uint);
48 | function price1CumulativeLast() external view returns (uint);
49 | function kLast() external view returns (uint);
50 |
51 | function mint(address to) external returns (uint liquidity);
52 | function burn(address to) external returns (uint amount0, uint amount1);
53 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
54 | function skim(address to) external;
55 | function sync() external;
56 |
57 | function initialize(address, address) external;
58 | }
59 |
60 | // File: contracts/interfaces/IPancakeERC20.sol
61 |
62 | pragma solidity >=0.5.0;
63 |
64 | interface IPancakeERC20 {
65 | event Approval(address indexed owner, address indexed spender, uint value);
66 | event Transfer(address indexed from, address indexed to, uint value);
67 |
68 | function name() external pure returns (string memory);
69 | function symbol() external pure returns (string memory);
70 | function decimals() external pure returns (uint8);
71 | function totalSupply() external view returns (uint);
72 | function balanceOf(address owner) external view returns (uint);
73 | function allowance(address owner, address spender) external view returns (uint);
74 |
75 | function approve(address spender, uint value) external returns (bool);
76 | function transfer(address to, uint value) external returns (bool);
77 | function transferFrom(address from, address to, uint value) external returns (bool);
78 |
79 | function DOMAIN_SEPARATOR() external view returns (bytes32);
80 | function PERMIT_TYPEHASH() external pure returns (bytes32);
81 | function nonces(address owner) external view returns (uint);
82 |
83 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
84 | }
85 |
86 | // File: contracts/libraries/SafeMath.sol
87 |
88 | pragma solidity =0.5.16;
89 |
90 | // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
91 |
92 | library SafeMath {
93 | function add(uint x, uint y) internal pure returns (uint z) {
94 | require((z = x + y) >= x, 'ds-math-add-overflow');
95 | }
96 |
97 | function sub(uint x, uint y) internal pure returns (uint z) {
98 | require((z = x - y) <= x, 'ds-math-sub-underflow');
99 | }
100 |
101 | function mul(uint x, uint y) internal pure returns (uint z) {
102 | require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
103 | }
104 | }
105 |
106 | // File: contracts/PancakeERC20.sol
107 |
108 | pragma solidity =0.5.16;
109 |
110 |
111 |
112 | contract PancakeERC20 is IPancakeERC20 {
113 | using SafeMath for uint;
114 |
115 | string public constant name = 'Pancake LPs';
116 | string public constant symbol = 'Cake-LP';
117 | uint8 public constant decimals = 18;
118 | uint public totalSupply;
119 | mapping(address => uint) public balanceOf;
120 | mapping(address => mapping(address => uint)) public allowance;
121 |
122 | bytes32 public DOMAIN_SEPARATOR;
123 | // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
124 | bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
125 | mapping(address => uint) public nonces;
126 |
127 | event Approval(address indexed owner, address indexed spender, uint value);
128 | event Transfer(address indexed from, address indexed to, uint value);
129 |
130 | constructor() public {
131 | uint chainId;
132 | assembly {
133 | chainId := chainid
134 | }
135 | DOMAIN_SEPARATOR = keccak256(
136 | abi.encode(
137 | keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
138 | keccak256(bytes(name)),
139 | keccak256(bytes('1')),
140 | chainId,
141 | address(this)
142 | )
143 | );
144 | }
145 |
146 | function _mint(address to, uint value) internal {
147 | totalSupply = totalSupply.add(value);
148 | balanceOf[to] = balanceOf[to].add(value);
149 | emit Transfer(address(0), to, value);
150 | }
151 |
152 | function _burn(address from, uint value) internal {
153 | balanceOf[from] = balanceOf[from].sub(value);
154 | totalSupply = totalSupply.sub(value);
155 | emit Transfer(from, address(0), value);
156 | }
157 |
158 | function _approve(address owner, address spender, uint value) private {
159 | allowance[owner][spender] = value;
160 | emit Approval(owner, spender, value);
161 | }
162 |
163 | function _transfer(address from, address to, uint value) private {
164 | balanceOf[from] = balanceOf[from].sub(value);
165 | balanceOf[to] = balanceOf[to].add(value);
166 | emit Transfer(from, to, value);
167 | }
168 |
169 | function approve(address spender, uint value) external returns (bool) {
170 | _approve(msg.sender, spender, value);
171 | return true;
172 | }
173 |
174 | function transfer(address to, uint value) external returns (bool) {
175 | _transfer(msg.sender, to, value);
176 | return true;
177 | }
178 |
179 | function transferFrom(address from, address to, uint value) external returns (bool) {
180 | if (allowance[from][msg.sender] != uint(-1)) {
181 | allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
182 | }
183 | _transfer(from, to, value);
184 | return true;
185 | }
186 |
187 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
188 | require(deadline >= block.timestamp, 'Pancake: EXPIRED');
189 | bytes32 digest = keccak256(
190 | abi.encodePacked(
191 | '\x19\x01',
192 | DOMAIN_SEPARATOR,
193 | keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
194 | )
195 | );
196 | address recoveredAddress = ecrecover(digest, v, r, s);
197 | require(recoveredAddress != address(0) && recoveredAddress == owner, 'Pancake: INVALID_SIGNATURE');
198 | _approve(owner, spender, value);
199 | }
200 | }
201 |
202 | // File: contracts/libraries/Math.sol
203 |
204 | pragma solidity =0.5.16;
205 |
206 | // a library for performing various math operations
207 |
208 | library Math {
209 | function min(uint x, uint y) internal pure returns (uint z) {
210 | z = x < y ? x : y;
211 | }
212 |
213 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
214 | function sqrt(uint y) internal pure returns (uint z) {
215 | if (y > 3) {
216 | z = y;
217 | uint x = y / 2 + 1;
218 | while (x < z) {
219 | z = x;
220 | x = (y / x + x) / 2;
221 | }
222 | } else if (y != 0) {
223 | z = 1;
224 | }
225 | }
226 | }
227 |
228 | // File: contracts/libraries/UQ112x112.sol
229 |
230 | pragma solidity =0.5.16;
231 |
232 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
233 |
234 | // range: [0, 2**112 - 1]
235 | // resolution: 1 / 2**112
236 |
237 | library UQ112x112 {
238 | uint224 constant Q112 = 2**112;
239 |
240 | // encode a uint112 as a UQ112x112
241 | function encode(uint112 y) internal pure returns (uint224 z) {
242 | z = uint224(y) * Q112; // never overflows
243 | }
244 |
245 | // divide a UQ112x112 by a uint112, returning a UQ112x112
246 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
247 | z = x / uint224(y);
248 | }
249 | }
250 |
251 | // File: contracts/interfaces/IERC20.sol
252 |
253 | pragma solidity >=0.5.0;
254 |
255 | interface IERC20 {
256 | event Approval(address indexed owner, address indexed spender, uint value);
257 | event Transfer(address indexed from, address indexed to, uint value);
258 |
259 | function name() external view returns (string memory);
260 | function symbol() external view returns (string memory);
261 | function decimals() external view returns (uint8);
262 | function totalSupply() external view returns (uint);
263 | function balanceOf(address owner) external view returns (uint);
264 | function allowance(address owner, address spender) external view returns (uint);
265 |
266 | function approve(address spender, uint value) external returns (bool);
267 | function transfer(address to, uint value) external returns (bool);
268 | function transferFrom(address from, address to, uint value) external returns (bool);
269 | }
270 |
271 | // File: contracts/interfaces/IPancakeFactory.sol
272 |
273 | pragma solidity >=0.5.0;
274 |
275 | interface IPancakeFactory {
276 | event PairCreated(address indexed token0, address indexed token1, address pair, uint);
277 |
278 | function feeTo() external view returns (address);
279 | function feeToSetter() external view returns (address);
280 |
281 | function getPair(address tokenA, address tokenB) external view returns (address pair);
282 | function allPairs(uint) external view returns (address pair);
283 | function allPairsLength() external view returns (uint);
284 |
285 | function createPair(address tokenA, address tokenB) external returns (address pair);
286 |
287 | function setFeeTo(address) external;
288 | function setFeeToSetter(address) external;
289 | }
290 |
291 | // File: contracts/interfaces/IPancakeCallee.sol
292 |
293 | pragma solidity >=0.5.0;
294 |
295 | interface IPancakeCallee {
296 | function pancakeCall(address sender, uint amount0, uint amount1, bytes calldata data) external;
297 | }
298 |
299 | // File: contracts/PancakePair.sol
300 |
301 | pragma solidity =0.5.16;
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 | contract PancakePair is IPancakePair, PancakeERC20 {
311 | using SafeMath for uint;
312 | using UQ112x112 for uint224;
313 |
314 | uint public constant MINIMUM_LIQUIDITY = 10**3;
315 | bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
316 |
317 | address public factory;
318 | address public token0;
319 | address public token1;
320 |
321 | uint112 private reserve0; // uses single storage slot, accessible via getReserves
322 | uint112 private reserve1; // uses single storage slot, accessible via getReserves
323 | uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
324 |
325 | uint public price0CumulativeLast;
326 | uint public price1CumulativeLast;
327 | uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
328 |
329 | uint private unlocked = 1;
330 | modifier lock() {
331 | require(unlocked == 1, 'Pancake: LOCKED');
332 | unlocked = 0;
333 | _;
334 | unlocked = 1;
335 | }
336 |
337 | function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
338 | _reserve0 = reserve0;
339 | _reserve1 = reserve1;
340 | _blockTimestampLast = blockTimestampLast;
341 | }
342 |
343 | function _safeTransfer(address token, address to, uint value) private {
344 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
345 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'Pancake: TRANSFER_FAILED');
346 | }
347 |
348 | event Mint(address indexed sender, uint amount0, uint amount1);
349 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
350 | event Swap(
351 | address indexed sender,
352 | uint amount0In,
353 | uint amount1In,
354 | uint amount0Out,
355 | uint amount1Out,
356 | address indexed to
357 | );
358 | event Sync(uint112 reserve0, uint112 reserve1);
359 |
360 | constructor() public {
361 | factory = msg.sender;
362 | }
363 |
364 | // called once by the factory at time of deployment
365 | function initialize(address _token0, address _token1) external {
366 | require(msg.sender == factory, 'Pancake: FORBIDDEN'); // sufficient check
367 | token0 = _token0;
368 | token1 = _token1;
369 | }
370 |
371 | // update reserves and, on the first call per block, price accumulators
372 | function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
373 | require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'Pancake: OVERFLOW');
374 | uint32 blockTimestamp = uint32(block.timestamp % 2**32);
375 | uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
376 | if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
377 | // * never overflows, and + overflow is desired
378 | price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
379 | price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
380 | }
381 | reserve0 = uint112(balance0);
382 | reserve1 = uint112(balance1);
383 | blockTimestampLast = blockTimestamp;
384 | emit Sync(reserve0, reserve1);
385 | }
386 |
387 | // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
388 | function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
389 | address feeTo = IPancakeFactory(factory).feeTo();
390 | feeOn = feeTo != address(0);
391 | uint _kLast = kLast; // gas savings
392 | if (feeOn) {
393 | if (_kLast != 0) {
394 | uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
395 | uint rootKLast = Math.sqrt(_kLast);
396 | if (rootK > rootKLast) {
397 | uint numerator = totalSupply.mul(rootK.sub(rootKLast));
398 | uint denominator = rootK.mul(3).add(rootKLast);
399 | uint liquidity = numerator / denominator;
400 | if (liquidity > 0) _mint(feeTo, liquidity);
401 | }
402 | }
403 | } else if (_kLast != 0) {
404 | kLast = 0;
405 | }
406 | }
407 |
408 | // this low-level function should be called from a contract which performs important safety checks
409 | function mint(address to) external lock returns (uint liquidity) {
410 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
411 | uint balance0 = IERC20(token0).balanceOf(address(this));
412 | uint balance1 = IERC20(token1).balanceOf(address(this));
413 | uint amount0 = balance0.sub(_reserve0);
414 | uint amount1 = balance1.sub(_reserve1);
415 |
416 | bool feeOn = _mintFee(_reserve0, _reserve1);
417 | uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
418 | if (_totalSupply == 0) {
419 | liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
420 | _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
421 | } else {
422 | liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
423 | }
424 | require(liquidity > 0, 'Pancake: INSUFFICIENT_LIQUIDITY_MINTED');
425 | _mint(to, liquidity);
426 |
427 | _update(balance0, balance1, _reserve0, _reserve1);
428 | if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
429 | emit Mint(msg.sender, amount0, amount1);
430 | }
431 |
432 | // this low-level function should be called from a contract which performs important safety checks
433 | function burn(address to) external lock returns (uint amount0, uint amount1) {
434 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
435 | address _token0 = token0; // gas savings
436 | address _token1 = token1; // gas savings
437 | uint balance0 = IERC20(_token0).balanceOf(address(this));
438 | uint balance1 = IERC20(_token1).balanceOf(address(this));
439 | uint liquidity = balanceOf[address(this)];
440 |
441 | bool feeOn = _mintFee(_reserve0, _reserve1);
442 | uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
443 | amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
444 | amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
445 | require(amount0 > 0 && amount1 > 0, 'Pancake: INSUFFICIENT_LIQUIDITY_BURNED');
446 | _burn(address(this), liquidity);
447 | _safeTransfer(_token0, to, amount0);
448 | _safeTransfer(_token1, to, amount1);
449 | balance0 = IERC20(_token0).balanceOf(address(this));
450 | balance1 = IERC20(_token1).balanceOf(address(this));
451 |
452 | _update(balance0, balance1, _reserve0, _reserve1);
453 | if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
454 | emit Burn(msg.sender, amount0, amount1, to);
455 | }
456 |
457 | // this low-level function should be called from a contract which performs important safety checks
458 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
459 | require(amount0Out > 0 || amount1Out > 0, 'Pancake: INSUFFICIENT_OUTPUT_AMOUNT');
460 | (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
461 | require(amount0Out < _reserve0 && amount1Out < _reserve1, 'Pancake: INSUFFICIENT_LIQUIDITY');
462 |
463 | uint balance0;
464 | uint balance1;
465 | { // scope for _token{0,1}, avoids stack too deep errors
466 | address _token0 = token0;
467 | address _token1 = token1;
468 | require(to != _token0 && to != _token1, 'Pancake: INVALID_TO');
469 | if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
470 | if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
471 | if (data.length > 0) IPancakeCallee(to).pancakeCall(msg.sender, amount0Out, amount1Out, data);
472 | balance0 = IERC20(_token0).balanceOf(address(this));
473 | balance1 = IERC20(_token1).balanceOf(address(this));
474 | }
475 | uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
476 | uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
477 | require(amount0In > 0 || amount1In > 0, 'Pancake: INSUFFICIENT_INPUT_AMOUNT');
478 | { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
479 | uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(2));
480 | uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(2));
481 | require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'Pancake: K');
482 | }
483 |
484 | _update(balance0, balance1, _reserve0, _reserve1);
485 | emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
486 | }
487 |
488 | // force balances to match reserves
489 | function skim(address to) external lock {
490 | address _token0 = token0; // gas savings
491 | address _token1 = token1; // gas savings
492 | _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
493 | _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
494 | }
495 |
496 | // force reserves to match balances
497 | function sync() external lock {
498 | _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
499 | }
500 | }
--------------------------------------------------------------------------------
/backend/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .env
--------------------------------------------------------------------------------
/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "start": "node src/app.js"
4 | },
5 | "dependencies": {
6 | "axios": "^1.4.0",
7 | "dotenv": "^16.0.3",
8 | "ethers": "^5.4.7",
9 | "web3": "^1.9.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/backend/src/UniswapV2_V3.js:
--------------------------------------------------------------------------------
1 | const Web3 = require("web3");
2 | const dotenv = require("dotenv");
3 | const tokenABI = require("./abi/erc20.json");
4 | const flashyABI = require("./abi/flashloan.json");
5 | const uniswapv2ABI = require("./abi/uniswapV2Router.json");
6 | const ethers = require("ethers");
7 | const axios = require("axios");
8 | dotenv.config();
9 |
10 | const ETHER_UNITS = {
11 | noether: "0",
12 | wei: "1",
13 | kwei: "1000",
14 | Kwei: "1000",
15 | babbage: "1000",
16 | femtoether: "1000",
17 | mwei: "1000000",
18 | Mwei: "1000000",
19 | lovelace: "1000000",
20 | picoether: "1000000",
21 | gwei: "1000000000",
22 | Gwei: "1000000000",
23 | shannon: "1000000000",
24 | nanoether: "1000000000",
25 | nano: "1000000000",
26 | szabo: "1000000000000",
27 | microether: "1000000000000",
28 | micro: "1000000000000",
29 | finney: "1000000000000000",
30 | milliether: "1000000000000000",
31 | milli: "1000000000000000",
32 | ether: "1000000000000000000",
33 | kether: "1000000000000000000000",
34 | grand: "1000000000000000000000",
35 | mether: "1000000000000000000000000",
36 | gether: "1000000000000000000000000000",
37 | tether: "1000000000000000000000000000000",
38 | };
39 |
40 | const poolABIV3 = [
41 | ` function slot0() external view returns
42 | (uint160 sqrtPriceX96,
43 | int24 tick,
44 | uint16 observationIndex,
45 | uint16 observationCardinality,
46 | uint16 observationCardinalityNext,
47 | uint8 feeProtocol,
48 | bool unlocked)`,
49 | ];
50 |
51 | const factoryABIV3 = [
52 | ` function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool)`,
53 | ];
54 |
55 | const PRIV_KEY = process.env.KKEEYY;
56 | const RPC_URL = process.env.GOERLI_RPC_URL;
57 | const FLASH_LOAN_ARBITRAGE_ADDRESS = process.env.FLASHY_CONTRACT_ADDRESS;
58 | const ERC20_TOKEN_ADDRESS = process.env.TOKEN_TO_LOAN; // USDC Smart Contract
59 | const LOAN_AMOUNT = process.env.TEKEN_AMOUNT_TO_LOAN; // 100 USDC
60 | const WETH_ADDRESS = process.env.WETH_ADDRESS; // WETH Smart Contract
61 | const ROUTER_ADDRESS_V2 = process.env.UNISWAP_V2_ROUTER_ADDRESS; // Uniswap V2 Router Smart Contract
62 | const FACTORY_ADDRESS_V3 = process.env.UNISWAP_V3_FACTORY_ADDRESS; // Uniswap V3 Factory Smart Contract
63 | //now we use USDC token address on gerli network, and loan amount is 100 USDC
64 |
65 | const web3 = new Web3(RPC_URL);
66 | const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
67 | const myAccount = web3.eth.accounts.privateKeyToAccount(PRIV_KEY);
68 | const flashLoanArbitrageContract = new web3.eth.Contract(flashyABI, FLASH_LOAN_ARBITRAGE_ADDRESS);
69 | const erc20TokenContract = new web3.eth.Contract(tokenABI, ERC20_TOKEN_ADDRESS);
70 | const uniswapV2RouterContract = new web3.eth.Contract(uniswapv2ABI, ROUTER_ADDRESS_V2);
71 | const uniswapV3FactoryContract = new ethers.Contract(FACTORY_ADDRESS_V3, factoryABIV3, provider);
72 | let uniswapV3PoolContract;
73 |
74 | const getCurrentGasPrices = async () => {
75 | try {
76 | //this URL is for Ethereum mainnet and Ethereum testnets
77 | let GAS_STATION = `https://api.debank.com/chain/gas_price_dict_v2?chain=eth`;
78 | var response = await axios.get(GAS_STATION);
79 | var prices = {
80 | low: Math.floor(response.data.data.slow.price),
81 | medium: Math.floor(response.data.data.normal.price),
82 | high: Math.floor(response.data.data.fast.price),
83 | };
84 | return prices;
85 | } catch (error) {
86 | //console.log(error);
87 | return {
88 | low: 25000000000,
89 | medium: 26000000000,
90 | high: 30000000000,
91 | };
92 | }
93 | };
94 |
95 | const getUniswapV2Price = async () => {
96 | let price = 0;
97 | try {
98 | // constructor(chainId: ChainId, address: string, decimals: number, symbol?: string, name?: string);
99 | const tokenDecimals = await erc20TokenContract.methods.decimals().call();
100 | //console.log("Token Decimals: ", tokenDecimals);
101 | const ethUnitName = Object.keys(ETHER_UNITS).find((key) => Math.pow(10, tokenDecimals).toString() == ETHER_UNITS[key]);
102 | //console.log("ETH Unit: ", ethUnitName);
103 | let unitAmount = web3.utils.toWei("1", ethUnitName.toString());
104 | //console.log("Unit Amount:", unitAmount);
105 | const amountsOut = await uniswapV2RouterContract.methods.getAmountsOut(unitAmount, [ERC20_TOKEN_ADDRESS, WETH_ADDRESS]).call();
106 | //console.log("Amounts Out: ", amountsOut);
107 | const ethAmountOnWei = amountsOut[1];
108 | const ethAmount = web3.utils.fromWei(ethAmountOnWei.toString(), "ether");
109 | //console.log("ETH Amount: ", ethAmount);
110 | price = Number(ethAmount.toString());
111 | } catch (error) {
112 | console.log(error);
113 | }
114 | return price;
115 | };
116 |
117 | const getUniswapV3Price = async () => {
118 | let tokenPrice = 0;
119 | try {
120 | const slot0 = await uniswapV3PoolContract.slot0();
121 | const sqrtPriceX96 = web3.utils.toBN(slot0?.sqrtPriceX96._hex.toString());
122 |
123 | var priceX96, Q192;
124 | if (sqrtPriceX96.gt(web3.utils.toBN("0xffffffffffffffffffffffff")) === true) {
125 | let shiftedSqrtPriceX96 = sqrtPriceX96.div(web3.utils.toBN('18446744073709551616')); // 2^64 = 18446744073709551616
126 | priceX96 = shiftedSqrtPriceX96.mul(shiftedSqrtPriceX96);
127 | Q192 = web3.utils.toBN('18446744073709551616');
128 | }
129 | else {
130 | priceX96 = sqrtPriceX96.mul(sqrtPriceX96);
131 | Q192 = web3.utils.toBN("0x100000000000000000000000000000000000000000000000000000");
132 | }
133 | //console.log("priceX96 >>>> ", priceX96.toString());
134 | //console.log("Q192 >>>> ", Q192.toString());
135 |
136 | if (WETH_ADDRESS.toLowerCase() < ERC20_TOKEN_ADDRESS.toLowerCase())
137 | tokenPrice = Q192.div(priceX96);
138 | else
139 | tokenPrice = priceX96.div(Q192);
140 | } catch (error) {
141 | console.log(error, "this is the error for getPrice");
142 | }
143 | return 1 / Number(tokenPrice.toString());
144 | };
145 |
146 | const signAndSendTx = async (data, from, to) => {
147 | let currentGasPrice = await getCurrentGasPrices();
148 | var nonce = await web3.eth.getTransactionCount(myAccount.address, "pending");
149 | nonce = web3.utils.toHex(nonce);
150 | let encodedABI = data.encodeABI();
151 | let gasEst = await data.estimateGas({ from: myAccount.address });
152 |
153 | let tx = {
154 | from: from,
155 | to: to,
156 | gas: gasEst * 10,
157 | gasPrice: currentGasPrice.high,
158 | data: encodedABI,
159 | nonce,
160 | };
161 | console.log("tx ===> ", tx);
162 | let signedTx = await myAccount.signTransaction(tx);
163 | await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
164 | .on("transactionHash", function (hash) {
165 | console.log("ts hash = ", hash);
166 | })
167 | .on("receipt", function (receipt) {
168 | console.log("");
169 | console.log("---------------------- tx succeed ---------------------");
170 | console.log("");
171 | })
172 | .on("error", function (error, receipt) {
173 | console.log("");
174 | console.log("---------------------- tx failed ---------------------");
175 | console.error(" error : ", error);
176 | });
177 | };
178 |
179 | const processArbitrage = async (premiumAmountOnWeiToLoan, amountOnWeiToLoan) => {
180 | try {
181 | let myBalance = await erc20TokenContract.methods.balanceOf(myAccount.address).call();
182 | console.log("Wallet Balance: ", Number(myBalance));
183 | console.log("Premium Amount to Loan: ", premiumAmountOnWeiToLoan);
184 |
185 | const priceOnv2 = await getUniswapV2Price();
186 | console.log("Price(Uniswap V2): ", priceOnv2);
187 |
188 | const priceOnv3 = await getUniswapV3Price();
189 | console.log("Price(Uniswap V3): ", priceOnv3);
190 |
191 | let dex_path = 7;
192 | if (priceOnv2 > priceOnv3)
193 | dex_path = 0;
194 | else if (priceOnv2 < priceOnv3)
195 | dex_path = 1;
196 |
197 | if (Number(myBalance) >= premiumAmountOnWeiToLoan) {
198 | //deposit premium to platform
199 | // let transferPremiums = tokenContract.methods.transfer(
200 | // PLATFORM_ADDRESS,
201 | // premiumAmountOnWeiToLoan
202 | // );
203 | // await signAndSendTx(
204 | // transferPremiums,
205 | // bossWallet.address,
206 | // TOKEN_ADDRESS
207 | // );
208 | //do flash loan
209 | console.log("Amount to Loan: ", amountOnWeiToLoan, ", Dex Path: ", dex_path);
210 | let doFlashy = flashLoanArbitrageContract.methods.fn_RequestFlashLoan(ERC20_TOKEN_ADDRESS, amountOnWeiToLoan, dex_path);
211 | await signAndSendTx(doFlashy, myAccount.address, FLASH_LOAN_ARBITRAGE_ADDRESS);
212 | }
213 | else {
214 | console.log("Token balance error.");
215 | const tokenSymbol = await erc20TokenContract.methods.symbol().call();
216 | console.log(`You should deposit about ${Number(LOAN_AMOUNT) * 0.01} ${tokenSymbol} to platform smart contract before run flash loan.`);
217 | }
218 | }
219 | catch (error) {
220 | console.log("ERROR:");
221 | console.log(error.message);
222 | }
223 | }
224 |
225 | const sleep = (ms) => new Promise(r => setTimeout(r, ms));
226 |
227 | const main = async () => {
228 | const poolAddr = await uniswapV3FactoryContract.getPool(WETH_ADDRESS, ERC20_TOKEN_ADDRESS, 3000);
229 | uniswapV3PoolContract = new ethers.Contract(poolAddr, poolABIV3, provider);
230 |
231 | const tokenDecimals = await erc20TokenContract.methods.decimals().call();
232 | const ethUnitName = Object.keys(ETHER_UNITS).find((key) => Math.pow(10, tokenDecimals).toString() == ETHER_UNITS[key]);
233 | let premiumAmountOnWeiToLoan = web3.utils.toWei((Number(LOAN_AMOUNT) * 0.01).toString(), ethUnitName.toString());
234 | let amountOnWeiToLoan = web3.utils.toWei(LOAN_AMOUNT.toString(), ethUnitName.toString());
235 |
236 | let transCount = 1;
237 | while (true) {
238 | await processArbitrage(Number(premiumAmountOnWeiToLoan), Number(amountOnWeiToLoan));
239 | await sleep(1000);
240 | transCount--;
241 | if (transCount == 0)
242 | break;
243 | }
244 | };
245 |
246 | /*const test = async () => {
247 | setInterval(async () => {
248 | let v2Price = await getUniswapV2Price();
249 | let v3Price = await getUniswapV3Price();
250 | console.log("===========================");
251 | console.log("Uniswap V2 Price: ", v2Price);
252 | console.log("Uniswap V3 Price: ", v3Price);
253 | }, 1000);
254 | }
255 | test();*/
256 |
257 | /*const printAllLiquidityList = () => {
258 | const url = "https://api.pancakeswap.info/api/v2/pairs";
259 |
260 | fetch(url)
261 | .then(response => response.json())
262 | .then(data => {
263 | console.log(data);
264 | for (let pair of data.data) {
265 | console.log(pair.pairName);
266 | console.log(pair.token0);
267 | console.log(pair.token1);
268 | console.log(pair.reserve0);
269 | console.log(pair.reserve1);
270 | console.log(pair.totalSupply);
271 | }
272 | })
273 | .catch(error => console.error(error));
274 | }*/
275 |
276 | main();
277 |
--------------------------------------------------------------------------------
/backend/src/abi/arbitrage.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "stateMutability": "nonpayable",
5 | "type": "constructor"
6 | },
7 | {
8 | "anonymous": false,
9 | "inputs": [
10 | {
11 | "indexed": false,
12 | "internalType": "uint256",
13 | "name": "value",
14 | "type": "uint256"
15 | }
16 | ],
17 | "name": "Minner_fee",
18 | "type": "event"
19 | },
20 | {
21 | "anonymous": false,
22 | "inputs": [
23 | {
24 | "indexed": true,
25 | "internalType": "address",
26 | "name": "previousOwner",
27 | "type": "address"
28 | },
29 | {
30 | "indexed": true,
31 | "internalType": "address",
32 | "name": "newOwner",
33 | "type": "address"
34 | }
35 | ],
36 | "name": "OwnershipTransferred",
37 | "type": "event"
38 | },
39 | {
40 | "anonymous": false,
41 | "inputs": [
42 | {
43 | "indexed": false,
44 | "internalType": "address",
45 | "name": "sender",
46 | "type": "address"
47 | },
48 | {
49 | "indexed": false,
50 | "internalType": "uint256",
51 | "name": "value",
52 | "type": "uint256"
53 | }
54 | ],
55 | "name": "Received",
56 | "type": "event"
57 | },
58 | {
59 | "anonymous": false,
60 | "inputs": [
61 | {
62 | "indexed": false,
63 | "internalType": "address",
64 | "name": "to",
65 | "type": "address"
66 | },
67 | {
68 | "indexed": false,
69 | "internalType": "uint256",
70 | "name": "value",
71 | "type": "uint256"
72 | }
73 | ],
74 | "name": "Withdraw",
75 | "type": "event"
76 | },
77 | {
78 | "anonymous": false,
79 | "inputs": [
80 | {
81 | "indexed": false,
82 | "internalType": "address",
83 | "name": "to",
84 | "type": "address"
85 | },
86 | {
87 | "indexed": false,
88 | "internalType": "uint256",
89 | "name": "value",
90 | "type": "uint256"
91 | }
92 | ],
93 | "name": "Withdraw_token",
94 | "type": "event"
95 | },
96 | {
97 | "stateMutability": "payable",
98 | "type": "fallback"
99 | },
100 | {
101 | "inputs": [],
102 | "name": "owner",
103 | "outputs": [
104 | {
105 | "internalType": "address",
106 | "name": "",
107 | "type": "address"
108 | }
109 | ],
110 | "stateMutability": "view",
111 | "type": "function"
112 | },
113 | {
114 | "inputs": [],
115 | "name": "renounceOwnership",
116 | "outputs": [],
117 | "stateMutability": "nonpayable",
118 | "type": "function"
119 | },
120 | {
121 | "inputs": [
122 | {
123 | "internalType": "address",
124 | "name": "token",
125 | "type": "address"
126 | },
127 | {
128 | "internalType": "uint256",
129 | "name": "amount",
130 | "type": "uint256"
131 | }
132 | ],
133 | "name": "swapTokenWithWethOnPancakeswap",
134 | "outputs": [],
135 | "stateMutability": "nonpayable",
136 | "type": "function"
137 | },
138 | {
139 | "inputs": [
140 | {
141 | "internalType": "address",
142 | "name": "token",
143 | "type": "address"
144 | },
145 | {
146 | "internalType": "uint256",
147 | "name": "amount",
148 | "type": "uint256"
149 | }
150 | ],
151 | "name": "swapTokenWithWethOnSushiswap",
152 | "outputs": [],
153 | "stateMutability": "nonpayable",
154 | "type": "function"
155 | },
156 | {
157 | "inputs": [
158 | {
159 | "internalType": "address",
160 | "name": "tokenIn",
161 | "type": "address"
162 | },
163 | {
164 | "internalType": "address",
165 | "name": "tokenOut",
166 | "type": "address"
167 | },
168 | {
169 | "internalType": "uint256",
170 | "name": "amountIn",
171 | "type": "uint256"
172 | }
173 | ],
174 | "name": "swapTokensOnPancakeswap",
175 | "outputs": [],
176 | "stateMutability": "nonpayable",
177 | "type": "function"
178 | },
179 | {
180 | "inputs": [
181 | {
182 | "internalType": "address",
183 | "name": "tokenIn",
184 | "type": "address"
185 | },
186 | {
187 | "internalType": "address",
188 | "name": "tokenOut",
189 | "type": "address"
190 | },
191 | {
192 | "internalType": "uint256",
193 | "name": "amountIn",
194 | "type": "uint256"
195 | }
196 | ],
197 | "name": "swapTokensOnSushiswap",
198 | "outputs": [],
199 | "stateMutability": "nonpayable",
200 | "type": "function"
201 | },
202 | {
203 | "inputs": [
204 | {
205 | "internalType": "address",
206 | "name": "token0",
207 | "type": "address"
208 | },
209 | {
210 | "internalType": "address",
211 | "name": "token1",
212 | "type": "address"
213 | },
214 | {
215 | "internalType": "uint256",
216 | "name": "amount",
217 | "type": "uint256"
218 | },
219 | {
220 | "internalType": "bool",
221 | "name": "firstPancake",
222 | "type": "bool"
223 | }
224 | ],
225 | "name": "trade",
226 | "outputs": [],
227 | "stateMutability": "nonpayable",
228 | "type": "function"
229 | },
230 | {
231 | "inputs": [
232 | {
233 | "internalType": "address",
234 | "name": "newOwner",
235 | "type": "address"
236 | }
237 | ],
238 | "name": "transferOwnership",
239 | "outputs": [],
240 | "stateMutability": "nonpayable",
241 | "type": "function"
242 | },
243 | {
244 | "inputs": [
245 | {
246 | "internalType": "uint256",
247 | "name": "_amount",
248 | "type": "uint256"
249 | }
250 | ],
251 | "name": "withdraw",
252 | "outputs": [
253 | {
254 | "internalType": "bool",
255 | "name": "",
256 | "type": "bool"
257 | }
258 | ],
259 | "stateMutability": "nonpayable",
260 | "type": "function"
261 | },
262 | {
263 | "inputs": [
264 | {
265 | "internalType": "address",
266 | "name": "_token",
267 | "type": "address"
268 | }
269 | ],
270 | "name": "withdrawToken",
271 | "outputs": [
272 | {
273 | "internalType": "bool",
274 | "name": "",
275 | "type": "bool"
276 | }
277 | ],
278 | "stateMutability": "nonpayable",
279 | "type": "function"
280 | },
281 | {
282 | "inputs": [
283 | {
284 | "internalType": "uint8",
285 | "name": "_percentage",
286 | "type": "uint8"
287 | }
288 | ],
289 | "name": "withdrawWeth",
290 | "outputs": [
291 | {
292 | "internalType": "bool",
293 | "name": "",
294 | "type": "bool"
295 | }
296 | ],
297 | "stateMutability": "nonpayable",
298 | "type": "function"
299 | },
300 | {
301 | "stateMutability": "payable",
302 | "type": "receive"
303 | }
304 | ]
--------------------------------------------------------------------------------
/backend/src/abi/erc20.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "string",
6 | "name": "name_",
7 | "type": "string"
8 | },
9 | {
10 | "internalType": "string",
11 | "name": "symbol_",
12 | "type": "string"
13 | }
14 | ],
15 | "stateMutability": "nonpayable",
16 | "type": "constructor"
17 | },
18 | {
19 | "anonymous": false,
20 | "inputs": [
21 | {
22 | "indexed": true,
23 | "internalType": "address",
24 | "name": "owner",
25 | "type": "address"
26 | },
27 | {
28 | "indexed": true,
29 | "internalType": "address",
30 | "name": "spender",
31 | "type": "address"
32 | },
33 | {
34 | "indexed": false,
35 | "internalType": "uint256",
36 | "name": "value",
37 | "type": "uint256"
38 | }
39 | ],
40 | "name": "Approval",
41 | "type": "event"
42 | },
43 | {
44 | "anonymous": false,
45 | "inputs": [
46 | {
47 | "indexed": true,
48 | "internalType": "address",
49 | "name": "from",
50 | "type": "address"
51 | },
52 | {
53 | "indexed": true,
54 | "internalType": "address",
55 | "name": "to",
56 | "type": "address"
57 | },
58 | {
59 | "indexed": false,
60 | "internalType": "uint256",
61 | "name": "value",
62 | "type": "uint256"
63 | }
64 | ],
65 | "name": "Transfer",
66 | "type": "event"
67 | },
68 | {
69 | "inputs": [
70 | {
71 | "internalType": "address",
72 | "name": "owner",
73 | "type": "address"
74 | },
75 | {
76 | "internalType": "address",
77 | "name": "spender",
78 | "type": "address"
79 | }
80 | ],
81 | "name": "allowance",
82 | "outputs": [
83 | {
84 | "internalType": "uint256",
85 | "name": "",
86 | "type": "uint256"
87 | }
88 | ],
89 | "stateMutability": "view",
90 | "type": "function"
91 | },
92 | {
93 | "inputs": [
94 | {
95 | "internalType": "address",
96 | "name": "spender",
97 | "type": "address"
98 | },
99 | {
100 | "internalType": "uint256",
101 | "name": "amount",
102 | "type": "uint256"
103 | }
104 | ],
105 | "name": "approve",
106 | "outputs": [
107 | {
108 | "internalType": "bool",
109 | "name": "",
110 | "type": "bool"
111 | }
112 | ],
113 | "stateMutability": "nonpayable",
114 | "type": "function"
115 | },
116 | {
117 | "inputs": [
118 | {
119 | "internalType": "address",
120 | "name": "account",
121 | "type": "address"
122 | }
123 | ],
124 | "name": "balanceOf",
125 | "outputs": [
126 | {
127 | "internalType": "uint256",
128 | "name": "",
129 | "type": "uint256"
130 | }
131 | ],
132 | "stateMutability": "view",
133 | "type": "function"
134 | },
135 | {
136 | "inputs": [],
137 | "name": "decimals",
138 | "outputs": [
139 | {
140 | "internalType": "uint8",
141 | "name": "",
142 | "type": "uint8"
143 | }
144 | ],
145 | "stateMutability": "view",
146 | "type": "function"
147 | },
148 | {
149 | "inputs": [
150 | {
151 | "internalType": "address",
152 | "name": "spender",
153 | "type": "address"
154 | },
155 | {
156 | "internalType": "uint256",
157 | "name": "subtractedValue",
158 | "type": "uint256"
159 | }
160 | ],
161 | "name": "decreaseAllowance",
162 | "outputs": [
163 | {
164 | "internalType": "bool",
165 | "name": "",
166 | "type": "bool"
167 | }
168 | ],
169 | "stateMutability": "nonpayable",
170 | "type": "function"
171 | },
172 | {
173 | "inputs": [
174 | {
175 | "internalType": "address",
176 | "name": "spender",
177 | "type": "address"
178 | },
179 | {
180 | "internalType": "uint256",
181 | "name": "addedValue",
182 | "type": "uint256"
183 | }
184 | ],
185 | "name": "increaseAllowance",
186 | "outputs": [
187 | {
188 | "internalType": "bool",
189 | "name": "",
190 | "type": "bool"
191 | }
192 | ],
193 | "stateMutability": "nonpayable",
194 | "type": "function"
195 | },
196 | {
197 | "inputs": [],
198 | "name": "name",
199 | "outputs": [
200 | {
201 | "internalType": "string",
202 | "name": "",
203 | "type": "string"
204 | }
205 | ],
206 | "stateMutability": "view",
207 | "type": "function"
208 | },
209 | {
210 | "inputs": [],
211 | "name": "symbol",
212 | "outputs": [
213 | {
214 | "internalType": "string",
215 | "name": "",
216 | "type": "string"
217 | }
218 | ],
219 | "stateMutability": "view",
220 | "type": "function"
221 | },
222 | {
223 | "inputs": [],
224 | "name": "totalSupply",
225 | "outputs": [
226 | {
227 | "internalType": "uint256",
228 | "name": "",
229 | "type": "uint256"
230 | }
231 | ],
232 | "stateMutability": "view",
233 | "type": "function"
234 | },
235 | {
236 | "inputs": [
237 | {
238 | "internalType": "address",
239 | "name": "to",
240 | "type": "address"
241 | },
242 | {
243 | "internalType": "uint256",
244 | "name": "amount",
245 | "type": "uint256"
246 | }
247 | ],
248 | "name": "transfer",
249 | "outputs": [
250 | {
251 | "internalType": "bool",
252 | "name": "",
253 | "type": "bool"
254 | }
255 | ],
256 | "stateMutability": "nonpayable",
257 | "type": "function"
258 | },
259 | {
260 | "inputs": [
261 | {
262 | "internalType": "address",
263 | "name": "from",
264 | "type": "address"
265 | },
266 | {
267 | "internalType": "address",
268 | "name": "to",
269 | "type": "address"
270 | },
271 | {
272 | "internalType": "uint256",
273 | "name": "amount",
274 | "type": "uint256"
275 | }
276 | ],
277 | "name": "transferFrom",
278 | "outputs": [
279 | {
280 | "internalType": "bool",
281 | "name": "",
282 | "type": "bool"
283 | }
284 | ],
285 | "stateMutability": "nonpayable",
286 | "type": "function"
287 | }
288 | ]
--------------------------------------------------------------------------------
/backend/src/abi/flashloan.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "_addressProvider",
7 | "type": "address"
8 | }
9 | ],
10 | "stateMutability": "nonpayable",
11 | "type": "constructor"
12 | },
13 | {
14 | "anonymous": false,
15 | "inputs": [
16 | {
17 | "indexed": false,
18 | "internalType": "uint256",
19 | "name": "value",
20 | "type": "uint256"
21 | }
22 | ],
23 | "name": "Minner_fee",
24 | "type": "event"
25 | },
26 | {
27 | "anonymous": false,
28 | "inputs": [
29 | {
30 | "indexed": true,
31 | "internalType": "address",
32 | "name": "previousOwner",
33 | "type": "address"
34 | },
35 | {
36 | "indexed": true,
37 | "internalType": "address",
38 | "name": "newOwner",
39 | "type": "address"
40 | }
41 | ],
42 | "name": "OwnershipTransferred",
43 | "type": "event"
44 | },
45 | {
46 | "anonymous": false,
47 | "inputs": [
48 | {
49 | "indexed": false,
50 | "internalType": "address",
51 | "name": "sender",
52 | "type": "address"
53 | },
54 | {
55 | "indexed": false,
56 | "internalType": "uint256",
57 | "name": "value",
58 | "type": "uint256"
59 | }
60 | ],
61 | "name": "Received",
62 | "type": "event"
63 | },
64 | {
65 | "anonymous": false,
66 | "inputs": [
67 | {
68 | "indexed": false,
69 | "internalType": "address",
70 | "name": "to",
71 | "type": "address"
72 | },
73 | {
74 | "indexed": false,
75 | "internalType": "uint256",
76 | "name": "value",
77 | "type": "uint256"
78 | }
79 | ],
80 | "name": "Withdraw",
81 | "type": "event"
82 | },
83 | {
84 | "anonymous": false,
85 | "inputs": [
86 | {
87 | "indexed": false,
88 | "internalType": "address",
89 | "name": "to",
90 | "type": "address"
91 | },
92 | {
93 | "indexed": false,
94 | "internalType": "uint256",
95 | "name": "value",
96 | "type": "uint256"
97 | }
98 | ],
99 | "name": "Withdraw_token",
100 | "type": "event"
101 | },
102 | {
103 | "stateMutability": "payable",
104 | "type": "fallback"
105 | },
106 | {
107 | "inputs": [],
108 | "name": "ADDRESSES_PROVIDER",
109 | "outputs": [
110 | {
111 | "internalType": "contract IPoolAddressesProvider",
112 | "name": "",
113 | "type": "address"
114 | }
115 | ],
116 | "stateMutability": "view",
117 | "type": "function"
118 | },
119 | {
120 | "inputs": [],
121 | "name": "POOL",
122 | "outputs": [
123 | {
124 | "internalType": "contract IPool",
125 | "name": "",
126 | "type": "address"
127 | }
128 | ],
129 | "stateMutability": "view",
130 | "type": "function"
131 | },
132 | {
133 | "inputs": [
134 | {
135 | "internalType": "address",
136 | "name": "_asset01",
137 | "type": "address"
138 | },
139 | {
140 | "internalType": "address",
141 | "name": "_asset02",
142 | "type": "address"
143 | },
144 | {
145 | "internalType": "uint256",
146 | "name": "_amount",
147 | "type": "uint256"
148 | },
149 | {
150 | "internalType": "uint8",
151 | "name": "_dex_path",
152 | "type": "uint8"
153 | },
154 | {
155 | "internalType": "uint24",
156 | "name": "_fee",
157 | "type": "uint24"
158 | }
159 | ],
160 | "name": "arb_swap",
161 | "outputs": [],
162 | "stateMutability": "nonpayable",
163 | "type": "function"
164 | },
165 | {
166 | "inputs": [],
167 | "name": "close",
168 | "outputs": [],
169 | "stateMutability": "payable",
170 | "type": "function"
171 | },
172 | {
173 | "inputs": [
174 | {
175 | "internalType": "address",
176 | "name": "asset",
177 | "type": "address"
178 | },
179 | {
180 | "internalType": "uint256",
181 | "name": "amount",
182 | "type": "uint256"
183 | },
184 | {
185 | "internalType": "uint256",
186 | "name": "premium",
187 | "type": "uint256"
188 | },
189 | {
190 | "internalType": "address",
191 | "name": "initiator",
192 | "type": "address"
193 | },
194 | {
195 | "internalType": "bytes",
196 | "name": "params",
197 | "type": "bytes"
198 | }
199 | ],
200 | "name": "executeOperation",
201 | "outputs": [
202 | {
203 | "internalType": "bool",
204 | "name": "",
205 | "type": "bool"
206 | }
207 | ],
208 | "stateMutability": "nonpayable",
209 | "type": "function"
210 | },
211 | {
212 | "inputs": [
213 | {
214 | "internalType": "address",
215 | "name": "_token",
216 | "type": "address"
217 | },
218 | {
219 | "internalType": "uint256",
220 | "name": "_amount",
221 | "type": "uint256"
222 | },
223 | {
224 | "internalType": "uint8",
225 | "name": "dex_path",
226 | "type": "uint8"
227 | }
228 | ],
229 | "name": "fn_RequestFlashLoan",
230 | "outputs": [],
231 | "stateMutability": "nonpayable",
232 | "type": "function"
233 | },
234 | {
235 | "inputs": [],
236 | "name": "owner",
237 | "outputs": [
238 | {
239 | "internalType": "address",
240 | "name": "",
241 | "type": "address"
242 | }
243 | ],
244 | "stateMutability": "view",
245 | "type": "function"
246 | },
247 | {
248 | "inputs": [],
249 | "name": "renounceOwnership",
250 | "outputs": [],
251 | "stateMutability": "nonpayable",
252 | "type": "function"
253 | },
254 | {
255 | "inputs": [
256 | {
257 | "internalType": "address",
258 | "name": "newOwner",
259 | "type": "address"
260 | }
261 | ],
262 | "name": "transferOwnership",
263 | "outputs": [],
264 | "stateMutability": "nonpayable",
265 | "type": "function"
266 | },
267 | {
268 | "inputs": [],
269 | "name": "uni_router_v2",
270 | "outputs": [
271 | {
272 | "internalType": "contract IUniswapV2Router02",
273 | "name": "",
274 | "type": "address"
275 | }
276 | ],
277 | "stateMutability": "view",
278 | "type": "function"
279 | },
280 | {
281 | "inputs": [],
282 | "name": "uni_router_v3",
283 | "outputs": [
284 | {
285 | "internalType": "contract ISwapRouter",
286 | "name": "",
287 | "type": "address"
288 | }
289 | ],
290 | "stateMutability": "view",
291 | "type": "function"
292 | },
293 | {
294 | "inputs": [
295 | {
296 | "internalType": "address",
297 | "name": "_tokenIn",
298 | "type": "address"
299 | },
300 | {
301 | "internalType": "address",
302 | "name": "_tokenOut",
303 | "type": "address"
304 | },
305 | {
306 | "internalType": "uint256",
307 | "name": "_amountIn",
308 | "type": "uint256"
309 | }
310 | ],
311 | "name": "uni_v2",
312 | "outputs": [],
313 | "stateMutability": "nonpayable",
314 | "type": "function"
315 | },
316 | {
317 | "inputs": [
318 | {
319 | "internalType": "address",
320 | "name": "_tokenIn",
321 | "type": "address"
322 | },
323 | {
324 | "internalType": "address",
325 | "name": "_tokenOut",
326 | "type": "address"
327 | },
328 | {
329 | "internalType": "uint256",
330 | "name": "_amountIn",
331 | "type": "uint256"
332 | },
333 | {
334 | "internalType": "uint24",
335 | "name": "_fee",
336 | "type": "uint24"
337 | }
338 | ],
339 | "name": "uni_v3",
340 | "outputs": [],
341 | "stateMutability": "payable",
342 | "type": "function"
343 | },
344 | {
345 | "inputs": [],
346 | "name": "weth",
347 | "outputs": [
348 | {
349 | "internalType": "contract IWETH9",
350 | "name": "",
351 | "type": "address"
352 | }
353 | ],
354 | "stateMutability": "view",
355 | "type": "function"
356 | },
357 | {
358 | "inputs": [
359 | {
360 | "internalType": "uint256",
361 | "name": "_amount",
362 | "type": "uint256"
363 | }
364 | ],
365 | "name": "withdraw",
366 | "outputs": [
367 | {
368 | "internalType": "bool",
369 | "name": "",
370 | "type": "bool"
371 | }
372 | ],
373 | "stateMutability": "nonpayable",
374 | "type": "function"
375 | },
376 | {
377 | "inputs": [
378 | {
379 | "internalType": "address",
380 | "name": "_token",
381 | "type": "address"
382 | },
383 | {
384 | "internalType": "uint8",
385 | "name": "_percentage",
386 | "type": "uint8"
387 | },
388 | {
389 | "internalType": "uint8",
390 | "name": "_dex",
391 | "type": "uint8"
392 | },
393 | {
394 | "internalType": "uint24",
395 | "name": "_dexfee",
396 | "type": "uint24"
397 | }
398 | ],
399 | "name": "withdraw_filter",
400 | "outputs": [
401 | {
402 | "internalType": "bool",
403 | "name": "",
404 | "type": "bool"
405 | }
406 | ],
407 | "stateMutability": "nonpayable",
408 | "type": "function"
409 | },
410 | {
411 | "inputs": [
412 | {
413 | "internalType": "address",
414 | "name": "_token",
415 | "type": "address"
416 | }
417 | ],
418 | "name": "withdraw_token",
419 | "outputs": [
420 | {
421 | "internalType": "bool",
422 | "name": "",
423 | "type": "bool"
424 | }
425 | ],
426 | "stateMutability": "nonpayable",
427 | "type": "function"
428 | },
429 | {
430 | "inputs": [
431 | {
432 | "internalType": "uint8",
433 | "name": "_percentage",
434 | "type": "uint8"
435 | }
436 | ],
437 | "name": "withdraw_weth",
438 | "outputs": [
439 | {
440 | "internalType": "bool",
441 | "name": "",
442 | "type": "bool"
443 | }
444 | ],
445 | "stateMutability": "nonpayable",
446 | "type": "function"
447 | },
448 | {
449 | "stateMutability": "payable",
450 | "type": "receive"
451 | }
452 | ]
--------------------------------------------------------------------------------
/backend/src/abi/pancakeswapFactory.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "_feeToSetter",
7 | "type": "address"
8 | }
9 | ],
10 | "payable": false,
11 | "stateMutability": "nonpayable",
12 | "type": "constructor"
13 | },
14 | {
15 | "anonymous": false,
16 | "inputs": [
17 | {
18 | "indexed": true,
19 | "internalType": "address",
20 | "name": "token0",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": true,
25 | "internalType": "address",
26 | "name": "token1",
27 | "type": "address"
28 | },
29 | {
30 | "indexed": false,
31 | "internalType": "address",
32 | "name": "pair",
33 | "type": "address"
34 | },
35 | {
36 | "indexed": false,
37 | "internalType": "uint256",
38 | "name": "",
39 | "type": "uint256"
40 | }
41 | ],
42 | "name": "PairCreated",
43 | "type": "event"
44 | },
45 | {
46 | "constant": true,
47 | "inputs": [],
48 | "name": "INIT_CODE_PAIR_HASH",
49 | "outputs": [
50 | {
51 | "internalType": "bytes32",
52 | "name": "",
53 | "type": "bytes32"
54 | }
55 | ],
56 | "payable": false,
57 | "stateMutability": "view",
58 | "type": "function"
59 | },
60 | {
61 | "constant": true,
62 | "inputs": [
63 | {
64 | "internalType": "uint256",
65 | "name": "",
66 | "type": "uint256"
67 | }
68 | ],
69 | "name": "allPairs",
70 | "outputs": [
71 | {
72 | "internalType": "address",
73 | "name": "",
74 | "type": "address"
75 | }
76 | ],
77 | "payable": false,
78 | "stateMutability": "view",
79 | "type": "function"
80 | },
81 | {
82 | "constant": true,
83 | "inputs": [],
84 | "name": "allPairsLength",
85 | "outputs": [
86 | {
87 | "internalType": "uint256",
88 | "name": "",
89 | "type": "uint256"
90 | }
91 | ],
92 | "payable": false,
93 | "stateMutability": "view",
94 | "type": "function"
95 | },
96 | {
97 | "constant": false,
98 | "inputs": [
99 | {
100 | "internalType": "address",
101 | "name": "tokenA",
102 | "type": "address"
103 | },
104 | {
105 | "internalType": "address",
106 | "name": "tokenB",
107 | "type": "address"
108 | }
109 | ],
110 | "name": "createPair",
111 | "outputs": [
112 | {
113 | "internalType": "address",
114 | "name": "pair",
115 | "type": "address"
116 | }
117 | ],
118 | "payable": false,
119 | "stateMutability": "nonpayable",
120 | "type": "function"
121 | },
122 | {
123 | "constant": true,
124 | "inputs": [],
125 | "name": "feeTo",
126 | "outputs": [
127 | {
128 | "internalType": "address",
129 | "name": "",
130 | "type": "address"
131 | }
132 | ],
133 | "payable": false,
134 | "stateMutability": "view",
135 | "type": "function"
136 | },
137 | {
138 | "constant": true,
139 | "inputs": [],
140 | "name": "feeToSetter",
141 | "outputs": [
142 | {
143 | "internalType": "address",
144 | "name": "",
145 | "type": "address"
146 | }
147 | ],
148 | "payable": false,
149 | "stateMutability": "view",
150 | "type": "function"
151 | },
152 | {
153 | "constant": true,
154 | "inputs": [
155 | {
156 | "internalType": "address",
157 | "name": "",
158 | "type": "address"
159 | },
160 | {
161 | "internalType": "address",
162 | "name": "",
163 | "type": "address"
164 | }
165 | ],
166 | "name": "getPair",
167 | "outputs": [
168 | {
169 | "internalType": "address",
170 | "name": "",
171 | "type": "address"
172 | }
173 | ],
174 | "payable": false,
175 | "stateMutability": "view",
176 | "type": "function"
177 | },
178 | {
179 | "constant": false,
180 | "inputs": [
181 | {
182 | "internalType": "address",
183 | "name": "_feeTo",
184 | "type": "address"
185 | }
186 | ],
187 | "name": "setFeeTo",
188 | "outputs": [],
189 | "payable": false,
190 | "stateMutability": "nonpayable",
191 | "type": "function"
192 | },
193 | {
194 | "constant": false,
195 | "inputs": [
196 | {
197 | "internalType": "address",
198 | "name": "_feeToSetter",
199 | "type": "address"
200 | }
201 | ],
202 | "name": "setFeeToSetter",
203 | "outputs": [],
204 | "payable": false,
205 | "stateMutability": "nonpayable",
206 | "type": "function"
207 | }
208 | ]
--------------------------------------------------------------------------------
/backend/src/abi/pancakeswapPair.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "payable": false,
5 | "stateMutability": "nonpayable",
6 | "type": "constructor"
7 | },
8 | {
9 | "anonymous": false,
10 | "inputs": [
11 | {
12 | "indexed": true,
13 | "internalType": "address",
14 | "name": "owner",
15 | "type": "address"
16 | },
17 | {
18 | "indexed": true,
19 | "internalType": "address",
20 | "name": "spender",
21 | "type": "address"
22 | },
23 | {
24 | "indexed": false,
25 | "internalType": "uint256",
26 | "name": "value",
27 | "type": "uint256"
28 | }
29 | ],
30 | "name": "Approval",
31 | "type": "event"
32 | },
33 | {
34 | "anonymous": false,
35 | "inputs": [
36 | {
37 | "indexed": true,
38 | "internalType": "address",
39 | "name": "sender",
40 | "type": "address"
41 | },
42 | {
43 | "indexed": false,
44 | "internalType": "uint256",
45 | "name": "amount0",
46 | "type": "uint256"
47 | },
48 | {
49 | "indexed": false,
50 | "internalType": "uint256",
51 | "name": "amount1",
52 | "type": "uint256"
53 | },
54 | {
55 | "indexed": true,
56 | "internalType": "address",
57 | "name": "to",
58 | "type": "address"
59 | }
60 | ],
61 | "name": "Burn",
62 | "type": "event"
63 | },
64 | {
65 | "anonymous": false,
66 | "inputs": [
67 | {
68 | "indexed": true,
69 | "internalType": "address",
70 | "name": "sender",
71 | "type": "address"
72 | },
73 | {
74 | "indexed": false,
75 | "internalType": "uint256",
76 | "name": "amount0",
77 | "type": "uint256"
78 | },
79 | {
80 | "indexed": false,
81 | "internalType": "uint256",
82 | "name": "amount1",
83 | "type": "uint256"
84 | }
85 | ],
86 | "name": "Mint",
87 | "type": "event"
88 | },
89 | {
90 | "anonymous": false,
91 | "inputs": [
92 | {
93 | "indexed": true,
94 | "internalType": "address",
95 | "name": "sender",
96 | "type": "address"
97 | },
98 | {
99 | "indexed": false,
100 | "internalType": "uint256",
101 | "name": "amount0In",
102 | "type": "uint256"
103 | },
104 | {
105 | "indexed": false,
106 | "internalType": "uint256",
107 | "name": "amount1In",
108 | "type": "uint256"
109 | },
110 | {
111 | "indexed": false,
112 | "internalType": "uint256",
113 | "name": "amount0Out",
114 | "type": "uint256"
115 | },
116 | {
117 | "indexed": false,
118 | "internalType": "uint256",
119 | "name": "amount1Out",
120 | "type": "uint256"
121 | },
122 | {
123 | "indexed": true,
124 | "internalType": "address",
125 | "name": "to",
126 | "type": "address"
127 | }
128 | ],
129 | "name": "Swap",
130 | "type": "event"
131 | },
132 | {
133 | "anonymous": false,
134 | "inputs": [
135 | {
136 | "indexed": false,
137 | "internalType": "uint112",
138 | "name": "reserve0",
139 | "type": "uint112"
140 | },
141 | {
142 | "indexed": false,
143 | "internalType": "uint112",
144 | "name": "reserve1",
145 | "type": "uint112"
146 | }
147 | ],
148 | "name": "Sync",
149 | "type": "event"
150 | },
151 | {
152 | "anonymous": false,
153 | "inputs": [
154 | {
155 | "indexed": true,
156 | "internalType": "address",
157 | "name": "from",
158 | "type": "address"
159 | },
160 | {
161 | "indexed": true,
162 | "internalType": "address",
163 | "name": "to",
164 | "type": "address"
165 | },
166 | {
167 | "indexed": false,
168 | "internalType": "uint256",
169 | "name": "value",
170 | "type": "uint256"
171 | }
172 | ],
173 | "name": "Transfer",
174 | "type": "event"
175 | },
176 | {
177 | "constant": true,
178 | "inputs": [],
179 | "name": "DOMAIN_SEPARATOR",
180 | "outputs": [
181 | {
182 | "internalType": "bytes32",
183 | "name": "",
184 | "type": "bytes32"
185 | }
186 | ],
187 | "payable": false,
188 | "stateMutability": "view",
189 | "type": "function"
190 | },
191 | {
192 | "constant": true,
193 | "inputs": [],
194 | "name": "MINIMUM_LIQUIDITY",
195 | "outputs": [
196 | {
197 | "internalType": "uint256",
198 | "name": "",
199 | "type": "uint256"
200 | }
201 | ],
202 | "payable": false,
203 | "stateMutability": "view",
204 | "type": "function"
205 | },
206 | {
207 | "constant": true,
208 | "inputs": [],
209 | "name": "PERMIT_TYPEHASH",
210 | "outputs": [
211 | {
212 | "internalType": "bytes32",
213 | "name": "",
214 | "type": "bytes32"
215 | }
216 | ],
217 | "payable": false,
218 | "stateMutability": "view",
219 | "type": "function"
220 | },
221 | {
222 | "constant": true,
223 | "inputs": [
224 | {
225 | "internalType": "address",
226 | "name": "",
227 | "type": "address"
228 | },
229 | {
230 | "internalType": "address",
231 | "name": "",
232 | "type": "address"
233 | }
234 | ],
235 | "name": "allowance",
236 | "outputs": [
237 | {
238 | "internalType": "uint256",
239 | "name": "",
240 | "type": "uint256"
241 | }
242 | ],
243 | "payable": false,
244 | "stateMutability": "view",
245 | "type": "function"
246 | },
247 | {
248 | "constant": false,
249 | "inputs": [
250 | {
251 | "internalType": "address",
252 | "name": "spender",
253 | "type": "address"
254 | },
255 | {
256 | "internalType": "uint256",
257 | "name": "value",
258 | "type": "uint256"
259 | }
260 | ],
261 | "name": "approve",
262 | "outputs": [
263 | {
264 | "internalType": "bool",
265 | "name": "",
266 | "type": "bool"
267 | }
268 | ],
269 | "payable": false,
270 | "stateMutability": "nonpayable",
271 | "type": "function"
272 | },
273 | {
274 | "constant": true,
275 | "inputs": [
276 | {
277 | "internalType": "address",
278 | "name": "",
279 | "type": "address"
280 | }
281 | ],
282 | "name": "balanceOf",
283 | "outputs": [
284 | {
285 | "internalType": "uint256",
286 | "name": "",
287 | "type": "uint256"
288 | }
289 | ],
290 | "payable": false,
291 | "stateMutability": "view",
292 | "type": "function"
293 | },
294 | {
295 | "constant": false,
296 | "inputs": [
297 | {
298 | "internalType": "address",
299 | "name": "to",
300 | "type": "address"
301 | }
302 | ],
303 | "name": "burn",
304 | "outputs": [
305 | {
306 | "internalType": "uint256",
307 | "name": "amount0",
308 | "type": "uint256"
309 | },
310 | {
311 | "internalType": "uint256",
312 | "name": "amount1",
313 | "type": "uint256"
314 | }
315 | ],
316 | "payable": false,
317 | "stateMutability": "nonpayable",
318 | "type": "function"
319 | },
320 | {
321 | "constant": true,
322 | "inputs": [],
323 | "name": "decimals",
324 | "outputs": [
325 | {
326 | "internalType": "uint8",
327 | "name": "",
328 | "type": "uint8"
329 | }
330 | ],
331 | "payable": false,
332 | "stateMutability": "view",
333 | "type": "function"
334 | },
335 | {
336 | "constant": true,
337 | "inputs": [],
338 | "name": "factory",
339 | "outputs": [
340 | {
341 | "internalType": "address",
342 | "name": "",
343 | "type": "address"
344 | }
345 | ],
346 | "payable": false,
347 | "stateMutability": "view",
348 | "type": "function"
349 | },
350 | {
351 | "constant": true,
352 | "inputs": [],
353 | "name": "getReserves",
354 | "outputs": [
355 | {
356 | "internalType": "uint112",
357 | "name": "_reserve0",
358 | "type": "uint112"
359 | },
360 | {
361 | "internalType": "uint112",
362 | "name": "_reserve1",
363 | "type": "uint112"
364 | },
365 | {
366 | "internalType": "uint32",
367 | "name": "_blockTimestampLast",
368 | "type": "uint32"
369 | }
370 | ],
371 | "payable": false,
372 | "stateMutability": "view",
373 | "type": "function"
374 | },
375 | {
376 | "constant": false,
377 | "inputs": [
378 | {
379 | "internalType": "address",
380 | "name": "_token0",
381 | "type": "address"
382 | },
383 | {
384 | "internalType": "address",
385 | "name": "_token1",
386 | "type": "address"
387 | }
388 | ],
389 | "name": "initialize",
390 | "outputs": [],
391 | "payable": false,
392 | "stateMutability": "nonpayable",
393 | "type": "function"
394 | },
395 | {
396 | "constant": true,
397 | "inputs": [],
398 | "name": "kLast",
399 | "outputs": [
400 | {
401 | "internalType": "uint256",
402 | "name": "",
403 | "type": "uint256"
404 | }
405 | ],
406 | "payable": false,
407 | "stateMutability": "view",
408 | "type": "function"
409 | },
410 | {
411 | "constant": false,
412 | "inputs": [
413 | {
414 | "internalType": "address",
415 | "name": "to",
416 | "type": "address"
417 | }
418 | ],
419 | "name": "mint",
420 | "outputs": [
421 | {
422 | "internalType": "uint256",
423 | "name": "liquidity",
424 | "type": "uint256"
425 | }
426 | ],
427 | "payable": false,
428 | "stateMutability": "nonpayable",
429 | "type": "function"
430 | },
431 | {
432 | "constant": true,
433 | "inputs": [],
434 | "name": "name",
435 | "outputs": [
436 | {
437 | "internalType": "string",
438 | "name": "",
439 | "type": "string"
440 | }
441 | ],
442 | "payable": false,
443 | "stateMutability": "view",
444 | "type": "function"
445 | },
446 | {
447 | "constant": true,
448 | "inputs": [
449 | {
450 | "internalType": "address",
451 | "name": "",
452 | "type": "address"
453 | }
454 | ],
455 | "name": "nonces",
456 | "outputs": [
457 | {
458 | "internalType": "uint256",
459 | "name": "",
460 | "type": "uint256"
461 | }
462 | ],
463 | "payable": false,
464 | "stateMutability": "view",
465 | "type": "function"
466 | },
467 | {
468 | "constant": false,
469 | "inputs": [
470 | {
471 | "internalType": "address",
472 | "name": "owner",
473 | "type": "address"
474 | },
475 | {
476 | "internalType": "address",
477 | "name": "spender",
478 | "type": "address"
479 | },
480 | {
481 | "internalType": "uint256",
482 | "name": "value",
483 | "type": "uint256"
484 | },
485 | {
486 | "internalType": "uint256",
487 | "name": "deadline",
488 | "type": "uint256"
489 | },
490 | {
491 | "internalType": "uint8",
492 | "name": "v",
493 | "type": "uint8"
494 | },
495 | {
496 | "internalType": "bytes32",
497 | "name": "r",
498 | "type": "bytes32"
499 | },
500 | {
501 | "internalType": "bytes32",
502 | "name": "s",
503 | "type": "bytes32"
504 | }
505 | ],
506 | "name": "permit",
507 | "outputs": [],
508 | "payable": false,
509 | "stateMutability": "nonpayable",
510 | "type": "function"
511 | },
512 | {
513 | "constant": true,
514 | "inputs": [],
515 | "name": "price0CumulativeLast",
516 | "outputs": [
517 | {
518 | "internalType": "uint256",
519 | "name": "",
520 | "type": "uint256"
521 | }
522 | ],
523 | "payable": false,
524 | "stateMutability": "view",
525 | "type": "function"
526 | },
527 | {
528 | "constant": true,
529 | "inputs": [],
530 | "name": "price1CumulativeLast",
531 | "outputs": [
532 | {
533 | "internalType": "uint256",
534 | "name": "",
535 | "type": "uint256"
536 | }
537 | ],
538 | "payable": false,
539 | "stateMutability": "view",
540 | "type": "function"
541 | },
542 | {
543 | "constant": false,
544 | "inputs": [
545 | {
546 | "internalType": "address",
547 | "name": "to",
548 | "type": "address"
549 | }
550 | ],
551 | "name": "skim",
552 | "outputs": [],
553 | "payable": false,
554 | "stateMutability": "nonpayable",
555 | "type": "function"
556 | },
557 | {
558 | "constant": false,
559 | "inputs": [
560 | {
561 | "internalType": "uint256",
562 | "name": "amount0Out",
563 | "type": "uint256"
564 | },
565 | {
566 | "internalType": "uint256",
567 | "name": "amount1Out",
568 | "type": "uint256"
569 | },
570 | {
571 | "internalType": "address",
572 | "name": "to",
573 | "type": "address"
574 | },
575 | {
576 | "internalType": "bytes",
577 | "name": "data",
578 | "type": "bytes"
579 | }
580 | ],
581 | "name": "swap",
582 | "outputs": [],
583 | "payable": false,
584 | "stateMutability": "nonpayable",
585 | "type": "function"
586 | },
587 | {
588 | "constant": true,
589 | "inputs": [],
590 | "name": "symbol",
591 | "outputs": [
592 | {
593 | "internalType": "string",
594 | "name": "",
595 | "type": "string"
596 | }
597 | ],
598 | "payable": false,
599 | "stateMutability": "view",
600 | "type": "function"
601 | },
602 | {
603 | "constant": false,
604 | "inputs": [],
605 | "name": "sync",
606 | "outputs": [],
607 | "payable": false,
608 | "stateMutability": "nonpayable",
609 | "type": "function"
610 | },
611 | {
612 | "constant": true,
613 | "inputs": [],
614 | "name": "token0",
615 | "outputs": [
616 | {
617 | "internalType": "address",
618 | "name": "",
619 | "type": "address"
620 | }
621 | ],
622 | "payable": false,
623 | "stateMutability": "view",
624 | "type": "function"
625 | },
626 | {
627 | "constant": true,
628 | "inputs": [],
629 | "name": "token1",
630 | "outputs": [
631 | {
632 | "internalType": "address",
633 | "name": "",
634 | "type": "address"
635 | }
636 | ],
637 | "payable": false,
638 | "stateMutability": "view",
639 | "type": "function"
640 | },
641 | {
642 | "constant": true,
643 | "inputs": [],
644 | "name": "totalSupply",
645 | "outputs": [
646 | {
647 | "internalType": "uint256",
648 | "name": "",
649 | "type": "uint256"
650 | }
651 | ],
652 | "payable": false,
653 | "stateMutability": "view",
654 | "type": "function"
655 | },
656 | {
657 | "constant": false,
658 | "inputs": [
659 | {
660 | "internalType": "address",
661 | "name": "to",
662 | "type": "address"
663 | },
664 | {
665 | "internalType": "uint256",
666 | "name": "value",
667 | "type": "uint256"
668 | }
669 | ],
670 | "name": "transfer",
671 | "outputs": [
672 | {
673 | "internalType": "bool",
674 | "name": "",
675 | "type": "bool"
676 | }
677 | ],
678 | "payable": false,
679 | "stateMutability": "nonpayable",
680 | "type": "function"
681 | },
682 | {
683 | "constant": false,
684 | "inputs": [
685 | {
686 | "internalType": "address",
687 | "name": "from",
688 | "type": "address"
689 | },
690 | {
691 | "internalType": "address",
692 | "name": "to",
693 | "type": "address"
694 | },
695 | {
696 | "internalType": "uint256",
697 | "name": "value",
698 | "type": "uint256"
699 | }
700 | ],
701 | "name": "transferFrom",
702 | "outputs": [
703 | {
704 | "internalType": "bool",
705 | "name": "",
706 | "type": "bool"
707 | }
708 | ],
709 | "payable": false,
710 | "stateMutability": "nonpayable",
711 | "type": "function"
712 | }
713 | ]
--------------------------------------------------------------------------------
/backend/src/abi/sushiswapV2Factory.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "_feeToSetter",
7 | "type": "address"
8 | }
9 | ],
10 | "stateMutability": "nonpayable",
11 | "type": "constructor"
12 | },
13 | {
14 | "anonymous": false,
15 | "inputs": [
16 | {
17 | "indexed": true,
18 | "internalType": "address",
19 | "name": "token0",
20 | "type": "address"
21 | },
22 | {
23 | "indexed": true,
24 | "internalType": "address",
25 | "name": "token1",
26 | "type": "address"
27 | },
28 | {
29 | "indexed": false,
30 | "internalType": "address",
31 | "name": "pair",
32 | "type": "address"
33 | },
34 | {
35 | "indexed": false,
36 | "internalType": "uint256",
37 | "name": "",
38 | "type": "uint256"
39 | }
40 | ],
41 | "name": "PairCreated",
42 | "type": "event"
43 | },
44 | {
45 | "inputs": [
46 | {
47 | "internalType": "uint256",
48 | "name": "",
49 | "type": "uint256"
50 | }
51 | ],
52 | "name": "allPairs",
53 | "outputs": [
54 | {
55 | "internalType": "address",
56 | "name": "",
57 | "type": "address"
58 | }
59 | ],
60 | "stateMutability": "view",
61 | "type": "function"
62 | },
63 | {
64 | "inputs": [],
65 | "name": "allPairsLength",
66 | "outputs": [
67 | {
68 | "internalType": "uint256",
69 | "name": "",
70 | "type": "uint256"
71 | }
72 | ],
73 | "stateMutability": "view",
74 | "type": "function"
75 | },
76 | {
77 | "inputs": [
78 | {
79 | "internalType": "address",
80 | "name": "tokenA",
81 | "type": "address"
82 | },
83 | {
84 | "internalType": "address",
85 | "name": "tokenB",
86 | "type": "address"
87 | }
88 | ],
89 | "name": "createPair",
90 | "outputs": [
91 | {
92 | "internalType": "address",
93 | "name": "pair",
94 | "type": "address"
95 | }
96 | ],
97 | "stateMutability": "nonpayable",
98 | "type": "function"
99 | },
100 | {
101 | "inputs": [],
102 | "name": "feeTo",
103 | "outputs": [
104 | {
105 | "internalType": "address",
106 | "name": "",
107 | "type": "address"
108 | }
109 | ],
110 | "stateMutability": "view",
111 | "type": "function"
112 | },
113 | {
114 | "inputs": [],
115 | "name": "feeToSetter",
116 | "outputs": [
117 | {
118 | "internalType": "address",
119 | "name": "",
120 | "type": "address"
121 | }
122 | ],
123 | "stateMutability": "view",
124 | "type": "function"
125 | },
126 | {
127 | "inputs": [
128 | {
129 | "internalType": "address",
130 | "name": "",
131 | "type": "address"
132 | },
133 | {
134 | "internalType": "address",
135 | "name": "",
136 | "type": "address"
137 | }
138 | ],
139 | "name": "getPair",
140 | "outputs": [
141 | {
142 | "internalType": "address",
143 | "name": "",
144 | "type": "address"
145 | }
146 | ],
147 | "stateMutability": "view",
148 | "type": "function"
149 | },
150 | {
151 | "inputs": [],
152 | "name": "migrator",
153 | "outputs": [
154 | {
155 | "internalType": "address",
156 | "name": "",
157 | "type": "address"
158 | }
159 | ],
160 | "stateMutability": "view",
161 | "type": "function"
162 | },
163 | {
164 | "inputs": [],
165 | "name": "pairCodeHash",
166 | "outputs": [
167 | {
168 | "internalType": "bytes32",
169 | "name": "",
170 | "type": "bytes32"
171 | }
172 | ],
173 | "stateMutability": "pure",
174 | "type": "function"
175 | },
176 | {
177 | "inputs": [
178 | {
179 | "internalType": "address",
180 | "name": "_feeTo",
181 | "type": "address"
182 | }
183 | ],
184 | "name": "setFeeTo",
185 | "outputs": [],
186 | "stateMutability": "nonpayable",
187 | "type": "function"
188 | },
189 | {
190 | "inputs": [
191 | {
192 | "internalType": "address",
193 | "name": "_feeToSetter",
194 | "type": "address"
195 | }
196 | ],
197 | "name": "setFeeToSetter",
198 | "outputs": [],
199 | "stateMutability": "nonpayable",
200 | "type": "function"
201 | },
202 | {
203 | "inputs": [
204 | {
205 | "internalType": "address",
206 | "name": "_migrator",
207 | "type": "address"
208 | }
209 | ],
210 | "name": "setMigrator",
211 | "outputs": [],
212 | "stateMutability": "nonpayable",
213 | "type": "function"
214 | }
215 | ]
--------------------------------------------------------------------------------
/backend/src/abi/uniswapV2Pair.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "stateMutability": "nonpayable",
5 | "type": "constructor"
6 | },
7 | {
8 | "anonymous": false,
9 | "inputs": [
10 | {
11 | "indexed": true,
12 | "internalType": "address",
13 | "name": "owner",
14 | "type": "address"
15 | },
16 | {
17 | "indexed": true,
18 | "internalType": "address",
19 | "name": "spender",
20 | "type": "address"
21 | },
22 | {
23 | "indexed": false,
24 | "internalType": "uint256",
25 | "name": "value",
26 | "type": "uint256"
27 | }
28 | ],
29 | "name": "Approval",
30 | "type": "event"
31 | },
32 | {
33 | "anonymous": false,
34 | "inputs": [
35 | {
36 | "indexed": true,
37 | "internalType": "address",
38 | "name": "sender",
39 | "type": "address"
40 | },
41 | {
42 | "indexed": false,
43 | "internalType": "uint256",
44 | "name": "amount0",
45 | "type": "uint256"
46 | },
47 | {
48 | "indexed": false,
49 | "internalType": "uint256",
50 | "name": "amount1",
51 | "type": "uint256"
52 | },
53 | {
54 | "indexed": true,
55 | "internalType": "address",
56 | "name": "to",
57 | "type": "address"
58 | }
59 | ],
60 | "name": "Burn",
61 | "type": "event"
62 | },
63 | {
64 | "anonymous": false,
65 | "inputs": [
66 | {
67 | "indexed": true,
68 | "internalType": "address",
69 | "name": "sender",
70 | "type": "address"
71 | },
72 | {
73 | "indexed": false,
74 | "internalType": "uint256",
75 | "name": "amount0",
76 | "type": "uint256"
77 | },
78 | {
79 | "indexed": false,
80 | "internalType": "uint256",
81 | "name": "amount1",
82 | "type": "uint256"
83 | }
84 | ],
85 | "name": "Mint",
86 | "type": "event"
87 | },
88 | {
89 | "anonymous": false,
90 | "inputs": [
91 | {
92 | "indexed": true,
93 | "internalType": "address",
94 | "name": "sender",
95 | "type": "address"
96 | },
97 | {
98 | "indexed": false,
99 | "internalType": "uint256",
100 | "name": "amount0In",
101 | "type": "uint256"
102 | },
103 | {
104 | "indexed": false,
105 | "internalType": "uint256",
106 | "name": "amount1In",
107 | "type": "uint256"
108 | },
109 | {
110 | "indexed": false,
111 | "internalType": "uint256",
112 | "name": "amount0Out",
113 | "type": "uint256"
114 | },
115 | {
116 | "indexed": false,
117 | "internalType": "uint256",
118 | "name": "amount1Out",
119 | "type": "uint256"
120 | },
121 | {
122 | "indexed": true,
123 | "internalType": "address",
124 | "name": "to",
125 | "type": "address"
126 | }
127 | ],
128 | "name": "Swap",
129 | "type": "event"
130 | },
131 | {
132 | "anonymous": false,
133 | "inputs": [
134 | {
135 | "indexed": false,
136 | "internalType": "uint112",
137 | "name": "reserve0",
138 | "type": "uint112"
139 | },
140 | {
141 | "indexed": false,
142 | "internalType": "uint112",
143 | "name": "reserve1",
144 | "type": "uint112"
145 | }
146 | ],
147 | "name": "Sync",
148 | "type": "event"
149 | },
150 | {
151 | "anonymous": false,
152 | "inputs": [
153 | {
154 | "indexed": true,
155 | "internalType": "address",
156 | "name": "from",
157 | "type": "address"
158 | },
159 | {
160 | "indexed": true,
161 | "internalType": "address",
162 | "name": "to",
163 | "type": "address"
164 | },
165 | {
166 | "indexed": false,
167 | "internalType": "uint256",
168 | "name": "value",
169 | "type": "uint256"
170 | }
171 | ],
172 | "name": "Transfer",
173 | "type": "event"
174 | },
175 | {
176 | "inputs": [],
177 | "name": "DOMAIN_SEPARATOR",
178 | "outputs": [
179 | {
180 | "internalType": "bytes32",
181 | "name": "",
182 | "type": "bytes32"
183 | }
184 | ],
185 | "stateMutability": "view",
186 | "type": "function"
187 | },
188 | {
189 | "inputs": [],
190 | "name": "MINIMUM_LIQUIDITY",
191 | "outputs": [
192 | {
193 | "internalType": "uint256",
194 | "name": "",
195 | "type": "uint256"
196 | }
197 | ],
198 | "stateMutability": "view",
199 | "type": "function"
200 | },
201 | {
202 | "inputs": [],
203 | "name": "PERMIT_TYPEHASH",
204 | "outputs": [
205 | {
206 | "internalType": "bytes32",
207 | "name": "",
208 | "type": "bytes32"
209 | }
210 | ],
211 | "stateMutability": "view",
212 | "type": "function"
213 | },
214 | {
215 | "inputs": [
216 | {
217 | "internalType": "address",
218 | "name": "",
219 | "type": "address"
220 | },
221 | {
222 | "internalType": "address",
223 | "name": "",
224 | "type": "address"
225 | }
226 | ],
227 | "name": "allowance",
228 | "outputs": [
229 | {
230 | "internalType": "uint256",
231 | "name": "",
232 | "type": "uint256"
233 | }
234 | ],
235 | "stateMutability": "view",
236 | "type": "function"
237 | },
238 | {
239 | "inputs": [
240 | {
241 | "internalType": "address",
242 | "name": "spender",
243 | "type": "address"
244 | },
245 | {
246 | "internalType": "uint256",
247 | "name": "value",
248 | "type": "uint256"
249 | }
250 | ],
251 | "name": "approve",
252 | "outputs": [
253 | {
254 | "internalType": "bool",
255 | "name": "",
256 | "type": "bool"
257 | }
258 | ],
259 | "stateMutability": "nonpayable",
260 | "type": "function"
261 | },
262 | {
263 | "inputs": [
264 | {
265 | "internalType": "address",
266 | "name": "",
267 | "type": "address"
268 | }
269 | ],
270 | "name": "balanceOf",
271 | "outputs": [
272 | {
273 | "internalType": "uint256",
274 | "name": "",
275 | "type": "uint256"
276 | }
277 | ],
278 | "stateMutability": "view",
279 | "type": "function"
280 | },
281 | {
282 | "inputs": [
283 | {
284 | "internalType": "address",
285 | "name": "to",
286 | "type": "address"
287 | }
288 | ],
289 | "name": "burn",
290 | "outputs": [
291 | {
292 | "internalType": "uint256",
293 | "name": "amount0",
294 | "type": "uint256"
295 | },
296 | {
297 | "internalType": "uint256",
298 | "name": "amount1",
299 | "type": "uint256"
300 | }
301 | ],
302 | "stateMutability": "nonpayable",
303 | "type": "function"
304 | },
305 | {
306 | "inputs": [],
307 | "name": "decimals",
308 | "outputs": [
309 | {
310 | "internalType": "uint8",
311 | "name": "",
312 | "type": "uint8"
313 | }
314 | ],
315 | "stateMutability": "view",
316 | "type": "function"
317 | },
318 | {
319 | "inputs": [],
320 | "name": "factory",
321 | "outputs": [
322 | {
323 | "internalType": "address",
324 | "name": "",
325 | "type": "address"
326 | }
327 | ],
328 | "stateMutability": "view",
329 | "type": "function"
330 | },
331 | {
332 | "inputs": [],
333 | "name": "getReserves",
334 | "outputs": [
335 | {
336 | "internalType": "uint112",
337 | "name": "_reserve0",
338 | "type": "uint112"
339 | },
340 | {
341 | "internalType": "uint112",
342 | "name": "_reserve1",
343 | "type": "uint112"
344 | },
345 | {
346 | "internalType": "uint32",
347 | "name": "_blockTimestampLast",
348 | "type": "uint32"
349 | }
350 | ],
351 | "stateMutability": "view",
352 | "type": "function"
353 | },
354 | {
355 | "inputs": [
356 | {
357 | "internalType": "address",
358 | "name": "_token0",
359 | "type": "address"
360 | },
361 | {
362 | "internalType": "address",
363 | "name": "_token1",
364 | "type": "address"
365 | }
366 | ],
367 | "name": "initialize",
368 | "outputs": [],
369 | "stateMutability": "nonpayable",
370 | "type": "function"
371 | },
372 | {
373 | "inputs": [],
374 | "name": "kLast",
375 | "outputs": [
376 | {
377 | "internalType": "uint256",
378 | "name": "",
379 | "type": "uint256"
380 | }
381 | ],
382 | "stateMutability": "view",
383 | "type": "function"
384 | },
385 | {
386 | "inputs": [
387 | {
388 | "internalType": "address",
389 | "name": "to",
390 | "type": "address"
391 | }
392 | ],
393 | "name": "mint",
394 | "outputs": [
395 | {
396 | "internalType": "uint256",
397 | "name": "liquidity",
398 | "type": "uint256"
399 | }
400 | ],
401 | "stateMutability": "nonpayable",
402 | "type": "function"
403 | },
404 | {
405 | "inputs": [],
406 | "name": "name",
407 | "outputs": [
408 | {
409 | "internalType": "string",
410 | "name": "",
411 | "type": "string"
412 | }
413 | ],
414 | "stateMutability": "view",
415 | "type": "function"
416 | },
417 | {
418 | "inputs": [
419 | {
420 | "internalType": "address",
421 | "name": "",
422 | "type": "address"
423 | }
424 | ],
425 | "name": "nonces",
426 | "outputs": [
427 | {
428 | "internalType": "uint256",
429 | "name": "",
430 | "type": "uint256"
431 | }
432 | ],
433 | "stateMutability": "view",
434 | "type": "function"
435 | },
436 | {
437 | "inputs": [
438 | {
439 | "internalType": "address",
440 | "name": "owner",
441 | "type": "address"
442 | },
443 | {
444 | "internalType": "address",
445 | "name": "spender",
446 | "type": "address"
447 | },
448 | {
449 | "internalType": "uint256",
450 | "name": "value",
451 | "type": "uint256"
452 | },
453 | {
454 | "internalType": "uint256",
455 | "name": "deadline",
456 | "type": "uint256"
457 | },
458 | {
459 | "internalType": "uint8",
460 | "name": "v",
461 | "type": "uint8"
462 | },
463 | {
464 | "internalType": "bytes32",
465 | "name": "r",
466 | "type": "bytes32"
467 | },
468 | {
469 | "internalType": "bytes32",
470 | "name": "s",
471 | "type": "bytes32"
472 | }
473 | ],
474 | "name": "permit",
475 | "outputs": [],
476 | "stateMutability": "nonpayable",
477 | "type": "function"
478 | },
479 | {
480 | "inputs": [],
481 | "name": "price0CumulativeLast",
482 | "outputs": [
483 | {
484 | "internalType": "uint256",
485 | "name": "",
486 | "type": "uint256"
487 | }
488 | ],
489 | "stateMutability": "view",
490 | "type": "function"
491 | },
492 | {
493 | "inputs": [],
494 | "name": "price1CumulativeLast",
495 | "outputs": [
496 | {
497 | "internalType": "uint256",
498 | "name": "",
499 | "type": "uint256"
500 | }
501 | ],
502 | "stateMutability": "view",
503 | "type": "function"
504 | },
505 | {
506 | "inputs": [
507 | {
508 | "internalType": "address",
509 | "name": "to",
510 | "type": "address"
511 | }
512 | ],
513 | "name": "skim",
514 | "outputs": [],
515 | "stateMutability": "nonpayable",
516 | "type": "function"
517 | },
518 | {
519 | "inputs": [
520 | {
521 | "internalType": "uint256",
522 | "name": "amount0Out",
523 | "type": "uint256"
524 | },
525 | {
526 | "internalType": "uint256",
527 | "name": "amount1Out",
528 | "type": "uint256"
529 | },
530 | {
531 | "internalType": "address",
532 | "name": "to",
533 | "type": "address"
534 | },
535 | {
536 | "internalType": "bytes",
537 | "name": "data",
538 | "type": "bytes"
539 | }
540 | ],
541 | "name": "swap",
542 | "outputs": [],
543 | "stateMutability": "nonpayable",
544 | "type": "function"
545 | },
546 | {
547 | "inputs": [],
548 | "name": "symbol",
549 | "outputs": [
550 | {
551 | "internalType": "string",
552 | "name": "",
553 | "type": "string"
554 | }
555 | ],
556 | "stateMutability": "view",
557 | "type": "function"
558 | },
559 | {
560 | "inputs": [],
561 | "name": "sync",
562 | "outputs": [],
563 | "stateMutability": "nonpayable",
564 | "type": "function"
565 | },
566 | {
567 | "inputs": [],
568 | "name": "token0",
569 | "outputs": [
570 | {
571 | "internalType": "address",
572 | "name": "",
573 | "type": "address"
574 | }
575 | ],
576 | "stateMutability": "view",
577 | "type": "function"
578 | },
579 | {
580 | "inputs": [],
581 | "name": "token1",
582 | "outputs": [
583 | {
584 | "internalType": "address",
585 | "name": "",
586 | "type": "address"
587 | }
588 | ],
589 | "stateMutability": "view",
590 | "type": "function"
591 | },
592 | {
593 | "inputs": [],
594 | "name": "totalSupply",
595 | "outputs": [
596 | {
597 | "internalType": "uint256",
598 | "name": "",
599 | "type": "uint256"
600 | }
601 | ],
602 | "stateMutability": "view",
603 | "type": "function"
604 | },
605 | {
606 | "inputs": [
607 | {
608 | "internalType": "address",
609 | "name": "to",
610 | "type": "address"
611 | },
612 | {
613 | "internalType": "uint256",
614 | "name": "value",
615 | "type": "uint256"
616 | }
617 | ],
618 | "name": "transfer",
619 | "outputs": [
620 | {
621 | "internalType": "bool",
622 | "name": "",
623 | "type": "bool"
624 | }
625 | ],
626 | "stateMutability": "nonpayable",
627 | "type": "function"
628 | },
629 | {
630 | "inputs": [
631 | {
632 | "internalType": "address",
633 | "name": "from",
634 | "type": "address"
635 | },
636 | {
637 | "internalType": "address",
638 | "name": "to",
639 | "type": "address"
640 | },
641 | {
642 | "internalType": "uint256",
643 | "name": "value",
644 | "type": "uint256"
645 | }
646 | ],
647 | "name": "transferFrom",
648 | "outputs": [
649 | {
650 | "internalType": "bool",
651 | "name": "",
652 | "type": "bool"
653 | }
654 | ],
655 | "stateMutability": "nonpayable",
656 | "type": "function"
657 | }
658 | ]
--------------------------------------------------------------------------------
/backend/src/abi/uniswapV2Router.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "address",
6 | "name": "_factory",
7 | "type": "address"
8 | },
9 | {
10 | "internalType": "address",
11 | "name": "_WETH",
12 | "type": "address"
13 | }
14 | ],
15 | "stateMutability": "nonpayable",
16 | "type": "constructor"
17 | },
18 | {
19 | "inputs": [],
20 | "name": "WETH",
21 | "outputs": [
22 | {
23 | "internalType": "address",
24 | "name": "",
25 | "type": "address"
26 | }
27 | ],
28 | "stateMutability": "view",
29 | "type": "function"
30 | },
31 | {
32 | "inputs": [
33 | {
34 | "internalType": "address",
35 | "name": "tokenA",
36 | "type": "address"
37 | },
38 | {
39 | "internalType": "address",
40 | "name": "tokenB",
41 | "type": "address"
42 | },
43 | {
44 | "internalType": "uint256",
45 | "name": "amountADesired",
46 | "type": "uint256"
47 | },
48 | {
49 | "internalType": "uint256",
50 | "name": "amountBDesired",
51 | "type": "uint256"
52 | },
53 | {
54 | "internalType": "uint256",
55 | "name": "amountAMin",
56 | "type": "uint256"
57 | },
58 | {
59 | "internalType": "uint256",
60 | "name": "amountBMin",
61 | "type": "uint256"
62 | },
63 | {
64 | "internalType": "address",
65 | "name": "to",
66 | "type": "address"
67 | },
68 | {
69 | "internalType": "uint256",
70 | "name": "deadline",
71 | "type": "uint256"
72 | }
73 | ],
74 | "name": "addLiquidity",
75 | "outputs": [
76 | {
77 | "internalType": "uint256",
78 | "name": "amountA",
79 | "type": "uint256"
80 | },
81 | {
82 | "internalType": "uint256",
83 | "name": "amountB",
84 | "type": "uint256"
85 | },
86 | {
87 | "internalType": "uint256",
88 | "name": "liquidity",
89 | "type": "uint256"
90 | }
91 | ],
92 | "stateMutability": "nonpayable",
93 | "type": "function"
94 | },
95 | {
96 | "inputs": [
97 | {
98 | "internalType": "address",
99 | "name": "token",
100 | "type": "address"
101 | },
102 | {
103 | "internalType": "uint256",
104 | "name": "amountTokenDesired",
105 | "type": "uint256"
106 | },
107 | {
108 | "internalType": "uint256",
109 | "name": "amountTokenMin",
110 | "type": "uint256"
111 | },
112 | {
113 | "internalType": "uint256",
114 | "name": "amountETHMin",
115 | "type": "uint256"
116 | },
117 | {
118 | "internalType": "address",
119 | "name": "to",
120 | "type": "address"
121 | },
122 | {
123 | "internalType": "uint256",
124 | "name": "deadline",
125 | "type": "uint256"
126 | }
127 | ],
128 | "name": "addLiquidityETH",
129 | "outputs": [
130 | {
131 | "internalType": "uint256",
132 | "name": "amountToken",
133 | "type": "uint256"
134 | },
135 | {
136 | "internalType": "uint256",
137 | "name": "amountETH",
138 | "type": "uint256"
139 | },
140 | {
141 | "internalType": "uint256",
142 | "name": "liquidity",
143 | "type": "uint256"
144 | }
145 | ],
146 | "stateMutability": "payable",
147 | "type": "function"
148 | },
149 | {
150 | "inputs": [],
151 | "name": "factory",
152 | "outputs": [
153 | {
154 | "internalType": "address",
155 | "name": "",
156 | "type": "address"
157 | }
158 | ],
159 | "stateMutability": "view",
160 | "type": "function"
161 | },
162 | {
163 | "inputs": [
164 | {
165 | "internalType": "uint256",
166 | "name": "amountOut",
167 | "type": "uint256"
168 | },
169 | {
170 | "internalType": "uint256",
171 | "name": "reserveIn",
172 | "type": "uint256"
173 | },
174 | {
175 | "internalType": "uint256",
176 | "name": "reserveOut",
177 | "type": "uint256"
178 | }
179 | ],
180 | "name": "getAmountIn",
181 | "outputs": [
182 | {
183 | "internalType": "uint256",
184 | "name": "amountIn",
185 | "type": "uint256"
186 | }
187 | ],
188 | "stateMutability": "pure",
189 | "type": "function"
190 | },
191 | {
192 | "inputs": [
193 | {
194 | "internalType": "uint256",
195 | "name": "amountIn",
196 | "type": "uint256"
197 | },
198 | {
199 | "internalType": "uint256",
200 | "name": "reserveIn",
201 | "type": "uint256"
202 | },
203 | {
204 | "internalType": "uint256",
205 | "name": "reserveOut",
206 | "type": "uint256"
207 | }
208 | ],
209 | "name": "getAmountOut",
210 | "outputs": [
211 | {
212 | "internalType": "uint256",
213 | "name": "amountOut",
214 | "type": "uint256"
215 | }
216 | ],
217 | "stateMutability": "pure",
218 | "type": "function"
219 | },
220 | {
221 | "inputs": [
222 | {
223 | "internalType": "uint256",
224 | "name": "amountOut",
225 | "type": "uint256"
226 | },
227 | {
228 | "internalType": "address[]",
229 | "name": "path",
230 | "type": "address[]"
231 | }
232 | ],
233 | "name": "getAmountsIn",
234 | "outputs": [
235 | {
236 | "internalType": "uint256[]",
237 | "name": "amounts",
238 | "type": "uint256[]"
239 | }
240 | ],
241 | "stateMutability": "view",
242 | "type": "function"
243 | },
244 | {
245 | "inputs": [
246 | {
247 | "internalType": "uint256",
248 | "name": "amountIn",
249 | "type": "uint256"
250 | },
251 | {
252 | "internalType": "address[]",
253 | "name": "path",
254 | "type": "address[]"
255 | }
256 | ],
257 | "name": "getAmountsOut",
258 | "outputs": [
259 | {
260 | "internalType": "uint256[]",
261 | "name": "amounts",
262 | "type": "uint256[]"
263 | }
264 | ],
265 | "stateMutability": "view",
266 | "type": "function"
267 | },
268 | {
269 | "inputs": [
270 | {
271 | "internalType": "uint256",
272 | "name": "amountA",
273 | "type": "uint256"
274 | },
275 | {
276 | "internalType": "uint256",
277 | "name": "reserveA",
278 | "type": "uint256"
279 | },
280 | {
281 | "internalType": "uint256",
282 | "name": "reserveB",
283 | "type": "uint256"
284 | }
285 | ],
286 | "name": "quote",
287 | "outputs": [
288 | {
289 | "internalType": "uint256",
290 | "name": "amountB",
291 | "type": "uint256"
292 | }
293 | ],
294 | "stateMutability": "pure",
295 | "type": "function"
296 | },
297 | {
298 | "inputs": [
299 | {
300 | "internalType": "address",
301 | "name": "tokenA",
302 | "type": "address"
303 | },
304 | {
305 | "internalType": "address",
306 | "name": "tokenB",
307 | "type": "address"
308 | },
309 | {
310 | "internalType": "uint256",
311 | "name": "liquidity",
312 | "type": "uint256"
313 | },
314 | {
315 | "internalType": "uint256",
316 | "name": "amountAMin",
317 | "type": "uint256"
318 | },
319 | {
320 | "internalType": "uint256",
321 | "name": "amountBMin",
322 | "type": "uint256"
323 | },
324 | {
325 | "internalType": "address",
326 | "name": "to",
327 | "type": "address"
328 | },
329 | {
330 | "internalType": "uint256",
331 | "name": "deadline",
332 | "type": "uint256"
333 | }
334 | ],
335 | "name": "removeLiquidity",
336 | "outputs": [
337 | {
338 | "internalType": "uint256",
339 | "name": "amountA",
340 | "type": "uint256"
341 | },
342 | {
343 | "internalType": "uint256",
344 | "name": "amountB",
345 | "type": "uint256"
346 | }
347 | ],
348 | "stateMutability": "nonpayable",
349 | "type": "function"
350 | },
351 | {
352 | "inputs": [
353 | {
354 | "internalType": "address",
355 | "name": "token",
356 | "type": "address"
357 | },
358 | {
359 | "internalType": "uint256",
360 | "name": "liquidity",
361 | "type": "uint256"
362 | },
363 | {
364 | "internalType": "uint256",
365 | "name": "amountTokenMin",
366 | "type": "uint256"
367 | },
368 | {
369 | "internalType": "uint256",
370 | "name": "amountETHMin",
371 | "type": "uint256"
372 | },
373 | {
374 | "internalType": "address",
375 | "name": "to",
376 | "type": "address"
377 | },
378 | {
379 | "internalType": "uint256",
380 | "name": "deadline",
381 | "type": "uint256"
382 | }
383 | ],
384 | "name": "removeLiquidityETH",
385 | "outputs": [
386 | {
387 | "internalType": "uint256",
388 | "name": "amountToken",
389 | "type": "uint256"
390 | },
391 | {
392 | "internalType": "uint256",
393 | "name": "amountETH",
394 | "type": "uint256"
395 | }
396 | ],
397 | "stateMutability": "nonpayable",
398 | "type": "function"
399 | },
400 | {
401 | "inputs": [
402 | {
403 | "internalType": "address",
404 | "name": "token",
405 | "type": "address"
406 | },
407 | {
408 | "internalType": "uint256",
409 | "name": "liquidity",
410 | "type": "uint256"
411 | },
412 | {
413 | "internalType": "uint256",
414 | "name": "amountTokenMin",
415 | "type": "uint256"
416 | },
417 | {
418 | "internalType": "uint256",
419 | "name": "amountETHMin",
420 | "type": "uint256"
421 | },
422 | {
423 | "internalType": "address",
424 | "name": "to",
425 | "type": "address"
426 | },
427 | {
428 | "internalType": "uint256",
429 | "name": "deadline",
430 | "type": "uint256"
431 | }
432 | ],
433 | "name": "removeLiquidityETHSupportingFeeOnTransferTokens",
434 | "outputs": [
435 | {
436 | "internalType": "uint256",
437 | "name": "amountETH",
438 | "type": "uint256"
439 | }
440 | ],
441 | "stateMutability": "nonpayable",
442 | "type": "function"
443 | },
444 | {
445 | "inputs": [
446 | {
447 | "internalType": "address",
448 | "name": "token",
449 | "type": "address"
450 | },
451 | {
452 | "internalType": "uint256",
453 | "name": "liquidity",
454 | "type": "uint256"
455 | },
456 | {
457 | "internalType": "uint256",
458 | "name": "amountTokenMin",
459 | "type": "uint256"
460 | },
461 | {
462 | "internalType": "uint256",
463 | "name": "amountETHMin",
464 | "type": "uint256"
465 | },
466 | {
467 | "internalType": "address",
468 | "name": "to",
469 | "type": "address"
470 | },
471 | {
472 | "internalType": "uint256",
473 | "name": "deadline",
474 | "type": "uint256"
475 | },
476 | {
477 | "internalType": "bool",
478 | "name": "approveMax",
479 | "type": "bool"
480 | },
481 | {
482 | "internalType": "uint8",
483 | "name": "v",
484 | "type": "uint8"
485 | },
486 | {
487 | "internalType": "bytes32",
488 | "name": "r",
489 | "type": "bytes32"
490 | },
491 | {
492 | "internalType": "bytes32",
493 | "name": "s",
494 | "type": "bytes32"
495 | }
496 | ],
497 | "name": "removeLiquidityETHWithPermit",
498 | "outputs": [
499 | {
500 | "internalType": "uint256",
501 | "name": "amountToken",
502 | "type": "uint256"
503 | },
504 | {
505 | "internalType": "uint256",
506 | "name": "amountETH",
507 | "type": "uint256"
508 | }
509 | ],
510 | "stateMutability": "nonpayable",
511 | "type": "function"
512 | },
513 | {
514 | "inputs": [
515 | {
516 | "internalType": "address",
517 | "name": "token",
518 | "type": "address"
519 | },
520 | {
521 | "internalType": "uint256",
522 | "name": "liquidity",
523 | "type": "uint256"
524 | },
525 | {
526 | "internalType": "uint256",
527 | "name": "amountTokenMin",
528 | "type": "uint256"
529 | },
530 | {
531 | "internalType": "uint256",
532 | "name": "amountETHMin",
533 | "type": "uint256"
534 | },
535 | {
536 | "internalType": "address",
537 | "name": "to",
538 | "type": "address"
539 | },
540 | {
541 | "internalType": "uint256",
542 | "name": "deadline",
543 | "type": "uint256"
544 | },
545 | {
546 | "internalType": "bool",
547 | "name": "approveMax",
548 | "type": "bool"
549 | },
550 | {
551 | "internalType": "uint8",
552 | "name": "v",
553 | "type": "uint8"
554 | },
555 | {
556 | "internalType": "bytes32",
557 | "name": "r",
558 | "type": "bytes32"
559 | },
560 | {
561 | "internalType": "bytes32",
562 | "name": "s",
563 | "type": "bytes32"
564 | }
565 | ],
566 | "name": "removeLiquidityETHWithPermitSupportingFeeOnTransferTokens",
567 | "outputs": [
568 | {
569 | "internalType": "uint256",
570 | "name": "amountETH",
571 | "type": "uint256"
572 | }
573 | ],
574 | "stateMutability": "nonpayable",
575 | "type": "function"
576 | },
577 | {
578 | "inputs": [
579 | {
580 | "internalType": "address",
581 | "name": "tokenA",
582 | "type": "address"
583 | },
584 | {
585 | "internalType": "address",
586 | "name": "tokenB",
587 | "type": "address"
588 | },
589 | {
590 | "internalType": "uint256",
591 | "name": "liquidity",
592 | "type": "uint256"
593 | },
594 | {
595 | "internalType": "uint256",
596 | "name": "amountAMin",
597 | "type": "uint256"
598 | },
599 | {
600 | "internalType": "uint256",
601 | "name": "amountBMin",
602 | "type": "uint256"
603 | },
604 | {
605 | "internalType": "address",
606 | "name": "to",
607 | "type": "address"
608 | },
609 | {
610 | "internalType": "uint256",
611 | "name": "deadline",
612 | "type": "uint256"
613 | },
614 | {
615 | "internalType": "bool",
616 | "name": "approveMax",
617 | "type": "bool"
618 | },
619 | {
620 | "internalType": "uint8",
621 | "name": "v",
622 | "type": "uint8"
623 | },
624 | {
625 | "internalType": "bytes32",
626 | "name": "r",
627 | "type": "bytes32"
628 | },
629 | {
630 | "internalType": "bytes32",
631 | "name": "s",
632 | "type": "bytes32"
633 | }
634 | ],
635 | "name": "removeLiquidityWithPermit",
636 | "outputs": [
637 | {
638 | "internalType": "uint256",
639 | "name": "amountA",
640 | "type": "uint256"
641 | },
642 | {
643 | "internalType": "uint256",
644 | "name": "amountB",
645 | "type": "uint256"
646 | }
647 | ],
648 | "stateMutability": "nonpayable",
649 | "type": "function"
650 | },
651 | {
652 | "inputs": [
653 | {
654 | "internalType": "uint256",
655 | "name": "amountOut",
656 | "type": "uint256"
657 | },
658 | {
659 | "internalType": "address[]",
660 | "name": "path",
661 | "type": "address[]"
662 | },
663 | {
664 | "internalType": "address",
665 | "name": "to",
666 | "type": "address"
667 | },
668 | {
669 | "internalType": "uint256",
670 | "name": "deadline",
671 | "type": "uint256"
672 | }
673 | ],
674 | "name": "swapETHForExactTokens",
675 | "outputs": [
676 | {
677 | "internalType": "uint256[]",
678 | "name": "amounts",
679 | "type": "uint256[]"
680 | }
681 | ],
682 | "stateMutability": "payable",
683 | "type": "function"
684 | },
685 | {
686 | "inputs": [
687 | {
688 | "internalType": "uint256",
689 | "name": "amountOutMin",
690 | "type": "uint256"
691 | },
692 | {
693 | "internalType": "address[]",
694 | "name": "path",
695 | "type": "address[]"
696 | },
697 | {
698 | "internalType": "address",
699 | "name": "to",
700 | "type": "address"
701 | },
702 | {
703 | "internalType": "uint256",
704 | "name": "deadline",
705 | "type": "uint256"
706 | }
707 | ],
708 | "name": "swapExactETHForTokens",
709 | "outputs": [
710 | {
711 | "internalType": "uint256[]",
712 | "name": "amounts",
713 | "type": "uint256[]"
714 | }
715 | ],
716 | "stateMutability": "payable",
717 | "type": "function"
718 | },
719 | {
720 | "inputs": [
721 | {
722 | "internalType": "uint256",
723 | "name": "amountOutMin",
724 | "type": "uint256"
725 | },
726 | {
727 | "internalType": "address[]",
728 | "name": "path",
729 | "type": "address[]"
730 | },
731 | {
732 | "internalType": "address",
733 | "name": "to",
734 | "type": "address"
735 | },
736 | {
737 | "internalType": "uint256",
738 | "name": "deadline",
739 | "type": "uint256"
740 | }
741 | ],
742 | "name": "swapExactETHForTokensSupportingFeeOnTransferTokens",
743 | "outputs": [],
744 | "stateMutability": "payable",
745 | "type": "function"
746 | },
747 | {
748 | "inputs": [
749 | {
750 | "internalType": "uint256",
751 | "name": "amountIn",
752 | "type": "uint256"
753 | },
754 | {
755 | "internalType": "uint256",
756 | "name": "amountOutMin",
757 | "type": "uint256"
758 | },
759 | {
760 | "internalType": "address[]",
761 | "name": "path",
762 | "type": "address[]"
763 | },
764 | {
765 | "internalType": "address",
766 | "name": "to",
767 | "type": "address"
768 | },
769 | {
770 | "internalType": "uint256",
771 | "name": "deadline",
772 | "type": "uint256"
773 | }
774 | ],
775 | "name": "swapExactTokensForETH",
776 | "outputs": [
777 | {
778 | "internalType": "uint256[]",
779 | "name": "amounts",
780 | "type": "uint256[]"
781 | }
782 | ],
783 | "stateMutability": "nonpayable",
784 | "type": "function"
785 | },
786 | {
787 | "inputs": [
788 | {
789 | "internalType": "uint256",
790 | "name": "amountIn",
791 | "type": "uint256"
792 | },
793 | {
794 | "internalType": "uint256",
795 | "name": "amountOutMin",
796 | "type": "uint256"
797 | },
798 | {
799 | "internalType": "address[]",
800 | "name": "path",
801 | "type": "address[]"
802 | },
803 | {
804 | "internalType": "address",
805 | "name": "to",
806 | "type": "address"
807 | },
808 | {
809 | "internalType": "uint256",
810 | "name": "deadline",
811 | "type": "uint256"
812 | }
813 | ],
814 | "name": "swapExactTokensForETHSupportingFeeOnTransferTokens",
815 | "outputs": [],
816 | "stateMutability": "nonpayable",
817 | "type": "function"
818 | },
819 | {
820 | "inputs": [
821 | {
822 | "internalType": "uint256",
823 | "name": "amountIn",
824 | "type": "uint256"
825 | },
826 | {
827 | "internalType": "uint256",
828 | "name": "amountOutMin",
829 | "type": "uint256"
830 | },
831 | {
832 | "internalType": "address[]",
833 | "name": "path",
834 | "type": "address[]"
835 | },
836 | {
837 | "internalType": "address",
838 | "name": "to",
839 | "type": "address"
840 | },
841 | {
842 | "internalType": "uint256",
843 | "name": "deadline",
844 | "type": "uint256"
845 | }
846 | ],
847 | "name": "swapExactTokensForTokens",
848 | "outputs": [
849 | {
850 | "internalType": "uint256[]",
851 | "name": "amounts",
852 | "type": "uint256[]"
853 | }
854 | ],
855 | "stateMutability": "nonpayable",
856 | "type": "function"
857 | },
858 | {
859 | "inputs": [
860 | {
861 | "internalType": "uint256",
862 | "name": "amountIn",
863 | "type": "uint256"
864 | },
865 | {
866 | "internalType": "uint256",
867 | "name": "amountOutMin",
868 | "type": "uint256"
869 | },
870 | {
871 | "internalType": "address[]",
872 | "name": "path",
873 | "type": "address[]"
874 | },
875 | {
876 | "internalType": "address",
877 | "name": "to",
878 | "type": "address"
879 | },
880 | {
881 | "internalType": "uint256",
882 | "name": "deadline",
883 | "type": "uint256"
884 | }
885 | ],
886 | "name": "swapExactTokensForTokensSupportingFeeOnTransferTokens",
887 | "outputs": [],
888 | "stateMutability": "nonpayable",
889 | "type": "function"
890 | },
891 | {
892 | "inputs": [
893 | {
894 | "internalType": "uint256",
895 | "name": "amountOut",
896 | "type": "uint256"
897 | },
898 | {
899 | "internalType": "uint256",
900 | "name": "amountInMax",
901 | "type": "uint256"
902 | },
903 | {
904 | "internalType": "address[]",
905 | "name": "path",
906 | "type": "address[]"
907 | },
908 | {
909 | "internalType": "address",
910 | "name": "to",
911 | "type": "address"
912 | },
913 | {
914 | "internalType": "uint256",
915 | "name": "deadline",
916 | "type": "uint256"
917 | }
918 | ],
919 | "name": "swapTokensForExactETH",
920 | "outputs": [
921 | {
922 | "internalType": "uint256[]",
923 | "name": "amounts",
924 | "type": "uint256[]"
925 | }
926 | ],
927 | "stateMutability": "nonpayable",
928 | "type": "function"
929 | },
930 | {
931 | "inputs": [
932 | {
933 | "internalType": "uint256",
934 | "name": "amountOut",
935 | "type": "uint256"
936 | },
937 | {
938 | "internalType": "uint256",
939 | "name": "amountInMax",
940 | "type": "uint256"
941 | },
942 | {
943 | "internalType": "address[]",
944 | "name": "path",
945 | "type": "address[]"
946 | },
947 | {
948 | "internalType": "address",
949 | "name": "to",
950 | "type": "address"
951 | },
952 | {
953 | "internalType": "uint256",
954 | "name": "deadline",
955 | "type": "uint256"
956 | }
957 | ],
958 | "name": "swapTokensForExactTokens",
959 | "outputs": [
960 | {
961 | "internalType": "uint256[]",
962 | "name": "amounts",
963 | "type": "uint256[]"
964 | }
965 | ],
966 | "stateMutability": "nonpayable",
967 | "type": "function"
968 | },
969 | {
970 | "stateMutability": "payable",
971 | "type": "receive"
972 | }
973 | ]
--------------------------------------------------------------------------------
/backend/src/app.js:
--------------------------------------------------------------------------------
1 | const http = require("http");
2 | const Web3 = require("web3");
3 | const dotenv = require("dotenv");
4 | const erc20ABI = require("./abi/erc20.json");
5 | const config = require("./config.json");
6 | const pancakeRouterABI = require("./abi/pancakeswapRouter.json");
7 | const pancakeFactoryABI = require("./abi/pancakeswapFactory.json");
8 | const pancakePairABI = require("./abi/pancakeswapPair.json");
9 | const sushiRouterABI = require("./abi/uniswapV2Router.json");
10 | const sushiFactoryABI = require("./abi/sushiswapV2Factory.json");
11 | const sushiPairABI = require("./abi/uniswapV2Pair.json");
12 | const arbitrageABI = require("./abi/arbitrage.json");
13 |
14 | dotenv.config();
15 |
16 | const host = 'localhost';
17 | const port = 8080;
18 |
19 | const requestListener = function(req, res) {
20 | res.writeHead(200);
21 | res.end("Hello World from Node.js HTTP Server");
22 | }
23 |
24 | const server = http.createServer(requestListener);
25 | server.listen(port, host, () => {
26 | console.log(`Server is running on http://${host}:${port}`);
27 | })
28 |
29 | const activeConfig = config["bsc_testnet"];
30 | const web3 = new Web3(activeConfig.RPC_URL);
31 | const myAccount = web3.eth.accounts.privateKeyToAccount(process.env.KKEEYY2);
32 |
33 | const pancakeRouterContract = new web3.eth.Contract(pancakeRouterABI, activeConfig.PANCAKE_ROUTER_ADDRESS);
34 | let pancakeFactoryContract, pancakePairContract;
35 |
36 | const sushiRouterContract = new web3.eth.Contract(sushiRouterABI, activeConfig.SUSHI_ROUTER_ADDRESS);
37 | let sushiFactoryContract, sushiPairContract;
38 |
39 | const arbitrageContract = activeConfig.ARBITRAGE_ADDRESS ? new web3.eth.Contract(arbitrageABI, activeConfig.ARBITRAGE_ADDRESS) : null;
40 | const token0Contract = new web3.eth.Contract(erc20ABI, activeConfig.TOKEN0);
41 |
42 | let priceEth = 0;
43 |
44 | const getCurrentGasPrices = async () => {
45 | try {
46 | //this URL is for Ethereum mainnet and Ethereum testnets
47 | let GAS_STATION = `https://api.debank.com/chain/gas_price_dict_v2?chain=bsc`;
48 | var response = await axios.get(GAS_STATION);
49 | var prices = {
50 | low: Math.floor(response.data.data.slow.price),
51 | medium: Math.floor(response.data.data.normal.price),
52 | high: Math.floor(response.data.data.fast.price),
53 | };
54 | return prices;
55 | } catch (error) {
56 | //console.log(error);
57 | const price = await web3.eth.getGasPrice();
58 | return {
59 | low: price,
60 | medium: price,
61 | high: price
62 | }
63 | }
64 | }
65 |
66 | const signAndSendTransaction = async (data, from, to, gas, gasPrice) => {
67 | var nonce = await web3.eth.getTransactionCount(from, "pending");
68 | nonce = web3.utils.toHex(nonce);
69 | let encodedABI = data.encodeABI();
70 |
71 | let tx = {
72 | from: from,
73 | to: to,
74 | gas: gas,
75 | gasPrice: gasPrice,
76 | data: encodedABI,
77 | nonce,
78 | };
79 | console.log("tx ===> ", tx);
80 | let signedTx = await myAccount.signTransaction(tx);
81 | await web3.eth.sendSignedTransaction(signedTx.rawTransaction)
82 | .on("transactionHash", (hash) => {
83 | console.log("ts hash = ", hash);
84 | })
85 | .on("receipt", async (receipt) => {
86 | console.log("");
87 | console.log("---------------------- tx succeed ---------------------");
88 | let balance = await token0Contract.methods.balanceOf(arbitrageContract.options.address).call();
89 | balance = Number(web3.utils.fromWei(balance.toString(), "ether"));
90 | console.log("Post-Balance:", balance);
91 | })
92 | .on("error", (error, receipt) => {
93 | console.log("");
94 | console.log("---------------------- tx failed ---------------------");
95 | console.error(" error : ", error);
96 | });
97 | };
98 |
99 | const printPairs = async (pancakeswap, count) => {
100 | let factoryContract;
101 | let pairABI;
102 | if (pancakeswap) {
103 | factoryContract = pancakeFactoryContract;
104 | pairABI = pancakePairABI;
105 | }
106 | else {
107 | factoryContract = sushiFactoryContract;
108 | pairABI = sushiPairABI;
109 | }
110 |
111 | let allPairsLength = await factoryContract.methods.allPairsLength().call();
112 | console.log(`Detected ${allPairsLength} pairs in ${pancakeswap ? "Pancakeswap" : "Sushiswap"}`);
113 |
114 | if (count > 0 && allPairsLength > count)
115 | allPairsLength = count;
116 |
117 | console.log(`${allPairsLength} Pairs in ${pancakeswap ? "Pancakeswap" : "Sushiswap"}`);
118 | for (let i = 0; i < allPairsLength; i++) {
119 | const pairAddr = await factoryContract.methods.allPairs(i).call();
120 | const pairContract = await new web3.eth.Contract(pairABI, pairAddr);
121 |
122 | const token0Addr = await pairContract.methods.token0().call();
123 | const token0Contract = await new web3.eth.Contract(erc20ABI, token0Addr);
124 | const token0Name = await token0Contract.methods.name().call();
125 | const token0Symbol = await token0Contract.methods.symbol().call();
126 |
127 | const token1Addr = await pairContract.methods.token1().call();
128 | const token1Contract = await new web3.eth.Contract(erc20ABI, token1Addr);
129 | const token1Name = await token1Contract.methods.name().call();
130 | const token1Symbol = await token1Contract.methods.symbol().call();
131 |
132 | console.log(`Pair ${i}: <${token0Addr}(${token0Name}, ${token0Symbol}) - ${token1Addr}(${token1Name}, ${token1Symbol})>`);
133 | }
134 | }
135 |
136 | const init = async (token0, token1) => {
137 | console.log("init -- Starting...");
138 |
139 | /* Initialize Pancakeswap Factory */
140 | const pancakeFactoryAddr = await pancakeRouterContract.methods.factory().call();
141 | pancakeFactoryContract = new web3.eth.Contract(pancakeFactoryABI, pancakeFactoryAddr);
142 |
143 | /* Initialize Sushiswap Factory */
144 | const sushiFactoryAddr = await sushiRouterContract.methods.factory().call();
145 | sushiFactoryContract = new web3.eth.Contract(sushiFactoryABI, sushiFactoryAddr);
146 |
147 | //await printPairs(true, 10);
148 | //await printPairs(false, 10);
149 |
150 | /* Initialize Pancakeswap */
151 | const pancakePairAddr = await pancakeFactoryContract.methods.getPair(token0, token1).call();
152 | pancakePairContract = new web3.eth.Contract(pancakePairABI, pancakePairAddr);
153 |
154 | console.log(`[Pancakeswap] router: ${activeConfig.PANCAKE_ROUTER_ADDRESS}, factory: ${pancakeFactoryAddr}, pair: ${pancakePairAddr}`);
155 |
156 | try {
157 | const ethDaiPairAddr = await pancakeFactoryContract.methods.getPair(activeConfig.DAI, activeConfig.ETH).call();
158 | const ethDaiPairContract = new web3.eth.Contract(pancakePairABI, ethDaiPairAddr);
159 | RR = await ethDaiPairContract.methods.getReserves().call();
160 | uReserve0 = RR[0]; //dai
161 | uReserve1 = RR[1]; //eth
162 | priceEth = RR[0] / RR[1]; //dai per eth
163 | console.log("ETH Price:", priceEth);
164 | }
165 | catch (error) {
166 | console.log(error);
167 | }
168 |
169 | /* Initialize Sushiswap */
170 | const sushiPairAddr = await sushiFactoryContract.methods.getPair(token0, token1).call();
171 | sushiPairContract = new web3.eth.Contract(sushiPairABI, sushiPairAddr);
172 |
173 | console.log(`[Sushiswap] router: ${activeConfig.SUSHI_ROUTER_ADDRESS}, factory: ${sushiFactoryAddr}, pair: ${sushiPairAddr}`);
174 |
175 | //const price0 = await getTokenPriceOnPancake();
176 | //const price1 = await getTokenPriceOnSushi();
177 | //console.log("Price(P):", price0, ", Price(S):", price1);
178 |
179 | console.log("init -- Done");
180 | }
181 |
182 | const getProfit = async (amountIn, firstPancake, PP, SS, gasFee) => {
183 | let profit;
184 | const amountIn2 = Number(web3.utils.fromWei(amountIn.toString(), "ether"));
185 | let fee = Number(web3.utils.fromWei(gasFee.toString(), "ether"));
186 | if (firstPancake) {
187 | const b = await pancakeRouterContract.methods.getAmountOut(amountIn, PP[0], PP[1]).call();
188 | const a = await sushiRouterContract.methods.getAmountOut(b, SS[1], SS[0]).call();
189 | let amountOut = Number(web3.utils.fromWei(a.toString(), "ether"));
190 | profit = (amountOut - amountIn2) / priceEth;
191 | }
192 | else {
193 | const b = await sushiRouterContract.methods.getAmountOut(amountIn, SS[0], SS[1]).call();
194 | const a = await pancakeRouterContract.methods.getAmountOut(b, PP[1], PP[0]).call();
195 | let amountOut = Number(web3.utils.fromWei(a.toString(), "ether"));
196 | profit = (amountOut - amountIn2) / priceEth;
197 | }
198 | profit -= fee;
199 | return profit;
200 | }
201 |
202 | const processArbitrage = async (token0, token1) => {
203 | try {
204 | let PP = await pancakePairContract.methods.getReserves().call();
205 | let SS = await sushiPairContract.methods.getReserves().call();
206 | const P1 = Number(web3.utils.fromWei(PP[1].toString(), "ether"));
207 | const P0 = Number(web3.utils.fromWei(PP[0].toString(), "ether"));
208 | const S1 = Number(web3.utils.fromWei(SS[1].toString(), "ether"));
209 | const S0 = Number(web3.utils.fromWei(SS[0].toString(), "ether"));
210 |
211 | let diffPrice = (P1 / P0) - (S1 / S0);
212 | if (diffPrice > -0.000000001 && diffPrice < 0.000000001) {
213 | console.log("Same prices!!! No arbitrage", diffPrice);
214 | return;
215 | }
216 |
217 | let firstPancake = diffPrice > 0;
218 | let amount;
219 | if (firstPancake) {
220 | amount = (P1 * S0 - P0 * S1) / (P1 + S1) / 2;
221 | }
222 | else {
223 | amount = (P0 * S1 - P1 * S0) / (P1 + S1) / 2;
224 | }
225 |
226 | console.log("Difference Price:", diffPrice);
227 | //console.log("Pancake:", P0, P1);
228 | //console.log("Sushi:", S0, S1);
229 | //console.log("Amount:", amount);
230 |
231 | let balance = await token0Contract.methods.balanceOf(arbitrageContract.options.address).call();
232 | balance = Number(web3.utils.fromWei(balance.toString(), "ether"));
233 | console.log("Pre-Balance:", balance);
234 | if (balance < amount) {
235 | let myBalance = await token0Contract.methods.balanceOf(myAccount.address).call();
236 | myBalance = Number(web3.utils.fromWei(myBalance.toString(), "ether"));
237 | console.log("My Balance:", myBalance);
238 |
239 | let neededAmount = amount - balance + 0.1;
240 | if (myBalance > neededAmount) {
241 | console.log("Transfering token from wallet to contract:", neededAmount);
242 | const amount2 = web3.utils.toWei(neededAmount.toString(), "ether");
243 | let transfering = token0Contract.methods.transfer(arbitrageContract.options.address, amount2);
244 | let currentGasPrice = await getCurrentGasPrices();
245 | let gasEst = await transfering.estimateGas({ from: myAccount.address });
246 | await signAndSendTransaction(transfering, myAccount.address, token0, gasEst, currentGasPrice.high);
247 | }
248 | else
249 | amount = balance;
250 |
251 | if (amount <= 0.000000001) {
252 | console.log("Insufficiant Balance, returing...");
253 | return;
254 | }
255 | }
256 |
257 | if (amount > 0) {
258 | amount = web3.utils.toWei(amount.toFixed(6).toString(), "ether");
259 | let trading = arbitrageContract.methods.trade(token0, token1, amount, firstPancake);
260 | const currentGasPrice = await getCurrentGasPrices();
261 | const gasEst = await trading.estimateGas({ from: myAccount.address });
262 | const gasPrice = currentGasPrice.high;
263 | console.log('Gasprice is:', gasPrice);
264 | let profit = await getProfit(amount, firstPancake, PP, SS, gasEst * Number(gasPrice));
265 | if (profit < 0) {
266 | console.log("No arbitrage!!!, Profit:", profit);
267 | return;
268 | }
269 | await signAndSendTransaction(trading, myAccount.address, arbitrageContract.options.address, gasEst, gasPrice);
270 | }
271 | }
272 | catch (error) {
273 | console.log(error);
274 | }
275 | }
276 |
277 | const sleep = (ms) => new Promise(r => setTimeout(r, ms));
278 |
279 | const main = async () => {
280 | await init(activeConfig.TOKEN0, activeConfig.TOKEN1);
281 |
282 | let maxCount = 0;
283 | while (true) {
284 | await processArbitrage(activeConfig.TOKEN0, activeConfig.TOKEN1);
285 | await sleep(100);
286 | if (maxCount > 0) {
287 | maxCount--;
288 | if (maxCount == 0)
289 | break;
290 | }
291 | }
292 | }
293 |
294 | main();
295 |
--------------------------------------------------------------------------------
/backend/src/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "bsc": {
3 | "RPC_URL": "https://bsc-dataseed.binance.org/",
4 | "ETH": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
5 | "DAI": "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3",
6 | "TOKEN0": "0x55d398326f99059fF775485246999027B3197955",
7 | "TOKEN1": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
8 | "PANCAKE_ROUTER_ADDRESS": "0x10ED43C718714eb63d5aA57B78B54704E256024E",
9 | "SUSHI_ROUTER_ADDRESS": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506",
10 | "ARBITRAGE_ADDRESS": ""
11 | },
12 | "bsc_testnet": {
13 | "RPC_URL": "https://data-seed-prebsc-1-s1.binance.org:8545/",
14 | "ETH": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
15 | "DAI": "0x8a9424745056Eb399FD19a0EC26A14316684e274",
16 | "TOKEN0": "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
17 | "TOKEN1": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
18 | "PANCAKE_ROUTER_ADDRESS": "0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3",
19 | "SUSHI_ROUTER_ADDRESS": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506",
20 | "ARBITRAGE_ADDRESS": "0x4Dfa4e5C4Cc4a0E1F31E73F01A67aE91BFBdB770"
21 | }
22 | }
--------------------------------------------------------------------------------
/backend/src/pancakeswap.js:
--------------------------------------------------------------------------------
1 | const Web3 = require('web3');
2 | const FactoryABI = require('./abi/pancakeswapFactory.json');
3 | const PairABI = require('./abi/pancakeswapPair.json');
4 | const ERC20ABI = require('./abi/erc20.json');
5 |
6 | const web3 = new Web3('https://bsc-dataseed.binance.org/');
7 | const pancakeFactoryAddress = '0xBCfCcbde45cE874adCB698cC183deBcF17952812';
8 | const pancakeFactoryContract = new web3.eth.Contract(FactoryABI, pancakeFactoryAddress);
9 |
10 | const printPairsOnPancakeswap = async () => {
11 | const allPairsLength = await pancakeFactoryContract.methods.allPairsLength().call();
12 | console.log(allPairsLength);
13 |
14 | for (let i = 0; i < /*allPairsLength*/10; i++) {
15 | const pairAddr = await pancakeFactoryContract.methods.allPairs(i).call();
16 | const pairContract = await new web3.eth.Contract(PairABI, pairAddr);
17 |
18 | const token0Addr = await pairContract.methods.token0().call();
19 | const token0Contract = await new web3.eth.Contract(ERC20ABI, token0Addr);
20 | //const token0Name = await token0Contract.methods.name().call();
21 | const token0Symbol = await token0Contract.methods.symbol().call();
22 |
23 | const token1Addr = await pairContract.methods.token1().call();
24 | const token1Contract = await new web3.eth.Contract(ERC20ABI, token1Addr);
25 | //const token1Name = await token1Contract.methods.name().call();
26 | const token1Symbol = await token1Contract.methods.symbol().call();
27 |
28 | console.log(`Pair ${i}: <${token0Addr}(${token0Symbol}), ${token1Addr}(${token1Symbol})>`);
29 | }
30 | }
31 |
32 | const getTokenPrice = async ()=> {
33 | const TOKEN0 = "0x55d398326f99059fF775485246999027B3197955"; // USDT
34 | const TOKEN1 = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; // WBNB
35 | const pairAddr = await pancakeFactoryContract.methods.getPair(TOKEN0, TOKEN1).call();
36 | const pairContract = await new web3.eth.Contract(PairABI, pairAddr);
37 |
38 | const reserves = await pairContract.methods.getReserves().call();
39 | const tokenPrice = reserves[1] / reserves[0];
40 | console.log(`Token price: ${tokenPrice}`);
41 | }
42 |
43 | getTokenPrice();
44 | //printPairsOnPancakeswap();
45 |
--------------------------------------------------------------------------------
/backend/src/sushiswap.js:
--------------------------------------------------------------------------------
1 | const Web3 = require('web3');
2 | //const RouterABI = require('./abi/uniswapV2Router.json');
3 | const FactoryABI = require('./abi/sushiswapV2Factory.json');
4 | const PairABI = require('./abi/uniswapV2Pair.json');
5 | const ERC20ABI = require('./abi/erc20.json');
6 |
7 | const web3 = new Web3('https://bsc-dataseed1.binance.org:443');
8 | //const sushiswapRouterAddress = '0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506';
9 | const sushiswapFactoryAddress = '0xc35DADB65012eC5796536bD9864eD8773aBc74C4';
10 |
11 | //const sushiswapRouter = new web3.eth.Contract(RouterABI, sushiswapRouterAddress);
12 | const sushiswapFactory = new web3.eth.Contract(FactoryABI, sushiswapFactoryAddress);
13 |
14 | const printPairsOnSushswap = async () => {
15 | const allPairsLength = await sushiswapFactory.methods.allPairsLength().call();
16 | console.log(allPairsLength);
17 |
18 | for (let i = 0; i < 10/*allPairsLength*/; i++) {
19 | const pairAddr = await sushiswapFactory.methods.allPairs(i).call();
20 | const pairContract = await new web3.eth.Contract(PairABI, pairAddr);
21 |
22 | const token0Addr = await pairContract.methods.token0().call();
23 | const token0Contract = await new web3.eth.Contract(ERC20ABI, token0Addr);
24 | //const token0Name = await token0Contract.methods.name().call();
25 | const token0Symbol = await token0Contract.methods.symbol().call();
26 |
27 | const token1Addr = await pairContract.methods.token1().call();
28 | const token1Contract = await new web3.eth.Contract(ERC20ABI, token1Addr);
29 | //const token1Name = await token1Contract.methods.name().call();
30 | const token1Symbol = await token1Contract.methods.symbol().call();
31 |
32 | console.log(`Pair ${i}: <${token0Addr}(${token0Symbol}), ${token1Addr}(${token1Symbol})>`);
33 | //const pair = await sushiswapRouter.methods.getPair(pairAddr, web3.utils.toChecksumAddress('0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c')).call();
34 | //if (pair !== '0x0000000000000000000000000000000000000000') {
35 | // console.log(pairAddr);
36 | //}
37 | }
38 | }
39 |
40 | printPairsOnSushswap();
--------------------------------------------------------------------------------
/frontend/index.js:
--------------------------------------------------------------------------------
1 | import { axios } from "axios";
2 |
3 | import { UPDATE_TX_LOG } from "../store/actions/action.types";
4 | import { updateTxLog } from "../store/actions/auth.actions";
5 |
6 | const Web3 = require("web3");
7 |
8 | const flashyABI = require("./json/flashloan.json");
9 | const tokenABI = require("./json/erc20.json");
10 | const uniswapv2ABI = require("./json/uniswapv2Router.json");
11 | const ethers = require("ethers");
12 | const store = require("../store/index").store;
13 |
14 | const ETHER_UNITS = {
15 | noether: "0",
16 | wei: "1",
17 | kwei: "1000",
18 | Kwei: "1000",
19 | babbage: "1000",
20 | femtoether: "1000",
21 | mwei: "1000000",
22 | Mwei: "1000000",
23 | lovelace: "1000000",
24 | picoether: "1000000",
25 | gwei: "1000000000",
26 | Gwei: "1000000000",
27 | shannon: "1000000000",
28 | nanoether: "1000000000",
29 | nano: "1000000000",
30 | szabo: "1000000000000",
31 | microether: "1000000000000",
32 | micro: "1000000000000",
33 | finney: "1000000000000000",
34 | milliether: "1000000000000000",
35 | milli: "1000000000000000",
36 | ether: "1000000000000000000",
37 | kether: "1000000000000000000000",
38 | grand: "1000000000000000000000",
39 | mether: "1000000000000000000000000",
40 | gether: "1000000000000000000000000000",
41 | tether: "1000000000000000000000000000000",
42 | };
43 |
44 | const poolABIV3 = [
45 | ` function slot0(
46 | ) external view returns
47 | (uint160 sqrtPriceX96,
48 | int24 tick,
49 | uint16 observationIndex,
50 | uint16 observationCardinality,
51 | uint16 observationCardinalityNext,
52 | uint8 feeProtocol,
53 | bool unlocked)`,
54 | ];
55 |
56 | const factoryABIV3 = [
57 | ` function getPool(
58 | address tokenA,
59 | address tokenB,
60 | uint24 fee
61 | ) external view returns (address pool)`,
62 | ];
63 |
64 | const KKEEYY = process.env.REACT_APP_KKEEYY;
65 | const RPC_URL = process.env.REACT_APP_GOERLI_RPC_URL;
66 | const PLATFORM_ADDRESS = process.env.REACT_APP_FLASHY_CONTRACT_ADDRESS;
67 | const TOKEN_ADDRESS = process.env.REACT_APP_TOKEN_TO_LOAN;
68 | const LOAN_AMOUNT = process.env.REACT_APP_TEKEN_AMOUNT_TO_LOAN;
69 | const WETH_ADDRESS = process.env.REACT_APP_WETH_ADDRESS;
70 | const ROUTER_ADDRESS_V2 = process.env.REACT_APP_UNISWAP_V2_ROUTER_ADDRESS;
71 | const FACTORY_ADDRESS_V3 = process.env.REACT_APP_UNISWAP_V3_FACTORY_ADDRESS;
72 | //now we use USDC token address on gerli network, and loan amount is 100 USDC
73 |
74 | const mainWeb3 = new Web3(RPC_URL);
75 | const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
76 | const bossWallet = mainWeb3.eth.accounts.privateKeyToAccount(KKEEYY);
77 | const flashyContract = new mainWeb3.eth.Contract(flashyABI, PLATFORM_ADDRESS);
78 | const tokenContract = new mainWeb3.eth.Contract(tokenABI, TOKEN_ADDRESS);
79 | const uniswapV2Contract = new mainWeb3.eth.Contract(
80 | uniswapv2ABI,
81 | ROUTER_ADDRESS_V2
82 | );
83 |
84 | const getUniswapV2Price = async () => {
85 | let price = 0;
86 | try {
87 | // constructor(chainId: ChainId, address: string, decimals: number, symbol?: string, name?: string);
88 | const tokenDecimals = await tokenContract.methods.decimals().call();
89 |
90 | const ethunitname = Object.keys(ETHER_UNITS).find(
91 | (key) => Math.pow(10, tokenDecimals).toString() == ETHER_UNITS[key]
92 | );
93 | let unitAmount = mainWeb3.utils.toWei("1", ethunitname.toString());
94 | const amountsOut = await uniswapV2Contract.methods
95 | .getAmountsOut(unitAmount, [TOKEN_ADDRESS, WETH_ADDRESS])
96 | .call();
97 | const ethAmountOnWei = amountsOut[1];
98 | const ethAmount = mainWeb3.utils.fromWei(
99 | ethAmountOnWei.toString(),
100 | "ether"
101 | );
102 |
103 | price = Number(ethAmount.toString());
104 | } catch (error) {
105 | console.log(error);
106 | throw error;
107 | }
108 | return price;
109 | };
110 |
111 | const getUniswapV3Price = async () => {
112 | let tokenPrice = 0;
113 | try {
114 | const factory = new ethers.Contract(
115 | FACTORY_ADDRESS_V3,
116 | factoryABIV3,
117 | provider
118 | );
119 | const poolAddress = await factory.getPool(
120 | WETH_ADDRESS,
121 | TOKEN_ADDRESS,
122 | 3000
123 | );
124 | const pool = new ethers.Contract(poolAddress, poolABIV3, provider);
125 | const slot0 = await pool.slot0();
126 |
127 | const sqrtPriceX96 = mainWeb3.utils.toBN(
128 | slot0?.sqrtPriceX96._hex.toString()
129 | );
130 |
131 | var priceX96, Q192;
132 |
133 | if (
134 | sqrtPriceX96.gt(mainWeb3.utils.toBN("0xffffffffffffffffffffffff")) ===
135 | true
136 | ) {
137 | let shiftedSqrtPriceX96 = sqrtPriceX96.div(
138 | mainWeb3.utils.toBN("18446744073709551616")
139 | ); // 2^64 = 18446744073709551616
140 | priceX96 = shiftedSqrtPriceX96.mul(shiftedSqrtPriceX96);
141 | Q192 = mainWeb3.utils.toBN("18446744073709551616");
142 | } else {
143 | priceX96 = sqrtPriceX96.mul(sqrtPriceX96);
144 | Q192 = mainWeb3.utils.toBN(
145 | "0x100000000000000000000000000000000000000000000000000000"
146 | );
147 | }
148 |
149 | if (WETH_ADDRESS.toLowerCase() < TOKEN_ADDRESS.toLowerCase()) {
150 | tokenPrice = Q192.div(priceX96);
151 | } else {
152 | tokenPrice = priceX96.div(Q192);
153 | }
154 | } catch (error) {
155 | console.log(error, "this is the error for getPrice");
156 | throw error;
157 | }
158 | return 1 / Number(tokenPrice.toString());
159 | };
160 |
161 | export const readEthBalanceOfUserWallet = async () => {
162 | let _tBalance = 0;
163 | try {
164 | _tBalance = await mainWeb3.eth.getBalance(bossWallet.address);
165 | _tBalance = mainWeb3.utils.fromWei(_tBalance.toString(), "ether");
166 | _tBalance = Number(_tBalance.toString());
167 | } catch (error) {
168 | console.log(error?.message);
169 | }
170 | return _tBalance;
171 | };
172 |
173 | export const readTokenBalanceOfContract = async () => {
174 | let _tBalance = 0;
175 | try {
176 | _tBalance = await tokenContract.methods.balanceOf(PLATFORM_ADDRESS).call();
177 |
178 | const tokenDecimals = await tokenContract.methods.decimals().call();
179 | const ethunitname = Object.keys(ETHER_UNITS).find(
180 | (key) => Math.pow(10, tokenDecimals).toString() == ETHER_UNITS[key]
181 | );
182 | _tBalance = mainWeb3.utils.fromWei(_tBalance.toString(), ethunitname);
183 | _tBalance = Number(_tBalance.toString());
184 | } catch (error) {
185 | console.log(error?.message);
186 | }
187 | return _tBalance;
188 | };
189 |
190 | export const readTokenBalanceOfUser = async () => {
191 | let _tBalance = 0;
192 | try {
193 | _tBalance = await tokenContract.methods
194 | .balanceOf(bossWallet.address)
195 | .call();
196 |
197 | const tokenDecimals = await tokenContract.methods.decimals().call();
198 | const ethunitname = Object.keys(ETHER_UNITS).find(
199 | (key) => Math.pow(10, tokenDecimals).toString() == ETHER_UNITS[key]
200 | );
201 | _tBalance = mainWeb3.utils.fromWei(_tBalance.toString(), ethunitname);
202 | _tBalance = Number(_tBalance.toString());
203 | } catch (error) {
204 | console.log(error?.message);
205 | }
206 | return _tBalance;
207 | };
208 |
209 | export const withdrawTokensToWallet = async () => {
210 | try {
211 | const doTokenWithdraw =
212 | flashyContract.methods.withdraw_token(TOKEN_ADDRESS);
213 | store.dispatch(updateTxLog(`
`));
214 | store.dispatch(
215 | updateTxLog(
216 | `
Withdrawing tokens from smart contract to your wallet.
` 217 | ) 218 | ); 219 | await signAndSendTx( 220 | doTokenWithdraw, 221 | bossWallet.address, 222 | PLATFORM_ADDRESS, 223 | true 224 | ); 225 | } catch (error) { 226 | throw error; 227 | } 228 | }; 229 | 230 | export const main = async () => { 231 | try { 232 | //check wether boss wallet has sufficient loan tokens 233 | const tokenDecimals = await tokenContract.methods.decimals().call(); 234 | const ethunitname = Object.keys(ETHER_UNITS).find( 235 | (key) => Math.pow(10, tokenDecimals).toString() == ETHER_UNITS[key] 236 | ); 237 | const premiumAmountOnWeiToLoan = mainWeb3.utils.toWei( 238 | Number(LOAN_AMOUNT).toString(), 239 | ethunitname.toString() 240 | ); 241 | 242 | let platformTokenBalance = await tokenContract.methods 243 | .balanceOf(PLATFORM_ADDRESS) 244 | .call(); 245 | 246 | platformTokenBalance = mainWeb3.utils.fromWei( 247 | platformTokenBalance.toString(), 248 | ethunitname 249 | ); 250 | 251 | console.log(platformTokenBalance.toString(), LOAN_AMOUNT.toString()); 252 | const priceOnv2 = await getUniswapV2Price(); 253 | 254 | console.log(`1 token = ${priceOnv2} ETH (Uniswap v2)`); 255 | store.dispatch(updateTxLog(`1 token = ${priceOnv2} ETH (Uniswap v2)
`) 258 | ); 259 | const priceOnv3 = await getUniswapV3Price(); 260 | console.log(`1 token = ${priceOnv3} ETH (Uniswap v3)`); 261 | store.dispatch( 262 | updateTxLog(`1 token = ${priceOnv3} ETH (Uniswap v3)
`) 263 | ); 264 | 265 | console.log("platformTokenBalance >>> ", platformTokenBalance); 266 | console.log("LOAN_AMOUNT >>> ", LOAN_AMOUNT); 267 | if (Number(platformTokenBalance.toString()) < Number(LOAN_AMOUNT)) { 268 | console.log("Token balance error."); 269 | const tokenSymbol = await tokenContract.methods.symbol().call(); 270 | console.log( 271 | `Depositing ${Number( 272 | LOAN_AMOUNT 273 | )} ${tokenSymbol} to platform smart contract.` 274 | ); 275 | store.dispatch( 276 | updateTxLog( 277 | `Depositing ${Number( 278 | LOAN_AMOUNT 279 | )} ${tokenSymbol} to platform smart contract.
` 280 | ) 281 | ); 282 | let transferPremiums = tokenContract.methods.transfer( 283 | PLATFORM_ADDRESS, 284 | premiumAmountOnWeiToLoan 285 | ); 286 | await signAndSendTx( 287 | transferPremiums, 288 | bossWallet.address, 289 | TOKEN_ADDRESS, 290 | true 291 | ); 292 | } 293 | 294 | let dex_path = 7; 295 | if (priceOnv3 > priceOnv2) { 296 | store.dispatch( 297 | updateTxLog( 298 | `Token price on Uniswap V3 is higher than price on Uniswap V2.
299 |So we sell tokens for ETH on Uniswap V3 first.
300 |And then we sell ETH for tokens on Uniswap V2.
` 301 | ) 302 | ); 303 | dex_path = 0; 304 | } else if (priceOnv3 < priceOnv2) { 305 | store.dispatch( 306 | updateTxLog( 307 | `Token price on Uniswap V2 is higher than price on Uniswap V3.
308 |So we sell tokens for ETH on Uniswap V2 first.
309 |And then we sell ETH for tokens on Uniswap V3.
` 310 | ) 311 | ); 312 | dex_path = 1; 313 | } else { 314 | console.log("Prices are equal!"); 315 | store.dispatch(updateTxLog(`Prices are equal.
`)); 316 | return; 317 | } 318 | 319 | const doSetFlag = flashyContract.methods.setDexFlag(dex_path); 320 | 321 | const amountOnWeiToLoan = mainWeb3.utils.toWei( 322 | LOAN_AMOUNT.toString(), 323 | ethunitname.toString() 324 | ); 325 | const doFlashy = flashyContract.methods.fn_RequestFlashLoan( 326 | TOKEN_ADDRESS, 327 | amountOnWeiToLoan 328 | ); 329 | let profitableETHAmount = LOAN_AMOUNT * Math.abs(priceOnv2 - priceOnv3); 330 | let txFee = 0; 331 | let gasprice = await mainWeb3.eth.getGasPrice(); 332 | let gasFee = await doSetFlag.estimateGas({ 333 | from: bossWallet.address, 334 | }); 335 | txFee += Number(Number(gasprice.toString()) * Number(gasFee.toString())); 336 | gasFee = await doFlashy.estimateGas({ 337 | from: bossWallet.address, 338 | }); 339 | txFee += Number(Number(gasprice.toString()) * Number(gasFee.toString())); 340 | const txFeeInETH = mainWeb3.utils.fromWei(txFee.toString(), "ether"); 341 | console.log( 342 | `so you can get ${ 343 | Number(profitableETHAmount.toString()) - Number(txFeeInETH.toString()) 344 | } ETH as profit if you trigger arbitrage transaction.` 345 | ); 346 | store.dispatch( 347 | updateTxLog( 348 | `You can get ${ 349 | Number(profitableETHAmount.toString()) - Number(txFeeInETH.toString()) 350 | } ETH as profit if you trigger arbitrage transaction.
` 351 | ) 352 | ); 353 | 354 | if ( 355 | Number(profitableETHAmount.toString()) - Number(txFeeInETH.toString()) > 356 | 0 357 | ) { 358 | console.log("Profitable! Now triggering arbitrage transaction..."); 359 | store.dispatch( 360 | updateTxLog(`Profitable! Now triggering arbitrage transaction...`) 361 | ); 362 | const currentflag = await flashyContract.methods.arb_swap_path().call(); 363 | console.log("currentflag >>>> ", currentflag, "dex_path >>> ", dex_path); 364 | if (Number(currentflag) !== Number(dex_path)) { 365 | store.dispatch(updateTxLog(`Aplying new flag...
`)); 366 | await signAndSendTx( 367 | doSetFlag, 368 | bossWallet.address, 369 | PLATFORM_ADDRESS, 370 | true 371 | ); 372 | } 373 | store.dispatch(updateTxLog(`Doing flash loan...
`)); 374 | await signAndSendTx(doFlashy, bossWallet.address, PLATFORM_ADDRESS, true); 375 | } 376 | } catch (error) { 377 | console.log(error.message); 378 | throw error; 379 | } 380 | }; 381 | 382 | const signAndSendTx = async (data, from, to, showPrintings = false) => { 383 | var nonce = await mainWeb3.eth.getTransactionCount( 384 | bossWallet.address, 385 | "pending" 386 | ); 387 | nonce = mainWeb3.utils.toHex(nonce); 388 | let encodedABI = data.encodeABI(); 389 | let gasFee = await data.estimateGas({ 390 | from: bossWallet.address, 391 | }); 392 | let gasprice = await mainWeb3.eth.getGasPrice(); 393 | let tx = { 394 | from: from, 395 | to: to, 396 | gas: gasFee * 10, 397 | gasPrice: gasprice.toString(), 398 | data: encodedABI, 399 | nonce, 400 | }; 401 | if (showPrintings) { 402 | console.log("tx ===> ", tx); 403 | } 404 | let signedTx = await bossWallet.signTransaction(tx); 405 | await mainWeb3.eth 406 | .sendSignedTransaction(signedTx.rawTransaction) 407 | .on("transactionHash", function (hash) { 408 | if (showPrintings) { 409 | console.log("ts hash = ", hash); 410 | store.dispatch(updateTxLog(`Transaction hash: ${hash}
`)); 411 | } 412 | }) 413 | .on("receipt", function (receipt) { 414 | if (showPrintings) { 415 | console.log(""); 416 | console.log("---------------------- tx succeed ---------------------"); 417 | console.log(""); 418 | 419 | store.dispatch( 420 | updateTxLog( 421 | "---------------------- tx succeed ---------------------
" 422 | ) 423 | ); 424 | } 425 | return true; 426 | }) 427 | .on("error", function (error, receipt) { 428 | if (showPrintings) { 429 | console.log(""); 430 | console.log("---------------------- tx failed ---------------------"); 431 | console.error(" error : ", error); 432 | 433 | store.dispatch( 434 | updateTxLog( 435 | "---------------------- tx failed ---------------------
" 436 | ) 437 | ); 438 | } 439 | return false; 440 | }); 441 | }; 442 | -------------------------------------------------------------------------------- /smartcontract/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | typechain-types 7 | secrets.json 8 | 9 | # Hardhat files 10 | cache 11 | artifacts 12 | 13 | -------------------------------------------------------------------------------- /smartcontract/contracts/FlashloanArbitrage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "@aave/core-v3/contracts/flashloan/base/FlashLoanSimpleReceiverBase.sol"; 6 | import "@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol"; 7 | import "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/Ownable.sol"; 8 | import { IERC20 } from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol"; 9 | import { SafeMath } from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeMath.sol"; 10 | import "hardhat/console.sol"; 11 | //import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 12 | 13 | // WETH 14 | interface IWETH9 { 15 | function withdraw(uint wad) external; 16 | } 17 | 18 | // Uniswap V2 19 | interface IUniswapV2Router01 { 20 | function swapExactTokensForTokens( 21 | uint amountIn, 22 | uint amountOutMin, 23 | address[] calldata path, 24 | address to, 25 | uint deadline 26 | ) external returns (uint[] memory amounts); 27 | 28 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); 29 | function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); 30 | } 31 | 32 | interface IUniswapV2Router02 is IUniswapV2Router01 { 33 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 34 | uint amountIn, 35 | uint amountOutMin, 36 | address[] calldata path, 37 | address to, 38 | uint deadline 39 | ) external; 40 | } 41 | 42 | // Uniswap V3 43 | library TransferHelper { 44 | function safeApprove(address token, address to, uint256 value) internal { 45 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); 46 | require(success && (data.length == 0 || abi.decode(data, (bool))), "SA"); 47 | } 48 | } 49 | 50 | interface IUniswapV3SwapCallback { 51 | function uniswapV3SwapCallback( 52 | int256 amount0Delta, 53 | int256 amount1Delta, 54 | bytes calldata data 55 | ) external; 56 | } 57 | 58 | interface ISwapRouter is IUniswapV3SwapCallback { 59 | struct ExactInputSingleParams { 60 | address tokenIn; 61 | address tokenOut; 62 | uint24 fee; 63 | address recipient; 64 | uint256 deadline; 65 | uint256 amountIn; 66 | uint256 amountOutMinimum; 67 | uint160 sqrtPriceLimitX96; 68 | } 69 | 70 | function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); 71 | 72 | struct ExactInputParams { 73 | bytes path; 74 | address recipient; 75 | uint256 deadline; 76 | uint256 amountIn; 77 | uint256 amountOutMinimum; 78 | } 79 | 80 | function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); 81 | } 82 | 83 | // Contract 84 | contract FlashloanArbitrage is FlashLoanSimpleReceiverBase, Ownable { 85 | enum DEX_PATH { 86 | UNIV3_UNIV2, 87 | UNIV2_UNIV3 88 | } 89 | 90 | enum DEX_Selection { 91 | UNIV2, 92 | UNIV3 93 | } 94 | 95 | using SafeMath for uint; 96 | 97 | uint8 private arb_swap_path = 1; 98 | uint24 private fee; 99 | 100 | IUniswapV2Router02 public constant uni_router_v2 = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); //Uniswap v2 Router on Goerli 101 | ISwapRouter public constant uni_router_v3 = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); //Uniswap v3 Router on Goerli 102 | IWETH9 public constant weth = IWETH9(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6); //weth on Goerli 103 | 104 | constructor(address _addressProvider) FlashLoanSimpleReceiverBase(IPoolAddressesProvider(_addressProvider)) {} 105 | 106 | // Events 107 | event Received(address sender, uint256 value); 108 | event Withdraw(address to, uint256 value); 109 | event Minner_fee(uint256 value); 110 | event Withdraw_token(address to, uint256 value); 111 | 112 | modifier checking_amount(address token, uint amount) { 113 | require(IERC20(token).balanceOf(address(this)) >= amount, "The amount exceeds balance!"); 114 | _; 115 | } 116 | 117 | receive() external payable {} 118 | 119 | fallback() external payable {} 120 | 121 | function withdraw(uint256 _amount) public onlyOwner returns (bool) { 122 | require(_amount <= address(this).balance, "Insufficient ETH amount!"); 123 | payable(msg.sender).transfer(_amount); 124 | 125 | emit Withdraw(msg.sender, _amount); 126 | return true; 127 | } 128 | 129 | function withdraw_weth(uint8 _percentage) public onlyOwner returns (bool) { 130 | require(IERC20(address(weth)).balanceOf(address(this)) > 0, "There is no WETH balance!"); 131 | require((0 < _percentage) && (_percentage <= 100), "Invalid percentage!"); 132 | 133 | weth.withdraw(IERC20(address(weth)).balanceOf(address(this))); 134 | 135 | uint256 amount_to_withdraw = SafeMath.mul(SafeMath.div(address(this).balance, 100), _percentage); 136 | block.coinbase.transfer(amount_to_withdraw); 137 | emit Minner_fee(amount_to_withdraw); 138 | 139 | return withdraw(address(this).balance); 140 | } 141 | 142 | function withdraw_token(address _token) public onlyOwner returns (bool) { 143 | uint256 balance = IERC20(_token).balanceOf(address(this)); 144 | require(balance > 0, "There is no token balance!"); 145 | bool check = IERC20(_token).transfer(msg.sender, balance); 146 | 147 | emit Withdraw_token(msg.sender, balance); 148 | return check; 149 | } 150 | 151 | function withdraw_filter(address _token, uint8 _percentage, uint8 _dex, uint24 _dexfee) public onlyOwner returns (bool) { 152 | if (_token == address(weth)) { 153 | return withdraw_weth(_percentage); 154 | } else { 155 | // The lines below are not the best way to proceed, because of we've aumented the number of txs however the payment for the minner is only allowed with WETH 156 | require(_dex < 2, "Invalid dex option for withdraw ETH!"); 157 | 158 | if (DEX_Selection.UNIV2 == DEX_Selection(_dex)) { 159 | uni_v2(_token, address(weth), IERC20(_token).balanceOf(address(this))); 160 | return withdraw_weth(_percentage); 161 | } 162 | if (DEX_Selection.UNIV3 == DEX_Selection(_dex)) { 163 | require((_dexfee == 500) || (_dexfee == 3000) || (_dexfee == 10000), "Invalid fee for swapping in UniV3"); 164 | uni_v3(_token, address(weth), IERC20(_token).balanceOf(address(this)), _dexfee); 165 | return withdraw_weth(_percentage); 166 | } 167 | return false; 168 | } 169 | } 170 | 171 | function get_path(address _tokenIn, address _tokenOut) internal pure returns (address[] memory) { 172 | address[] memory path; 173 | path = new address[](2); 174 | path[0] = _tokenIn; 175 | path[1] = _tokenOut; 176 | return path; 177 | } 178 | 179 | // Functions for swapping on 2 main dexes 180 | 181 | function uni_v2(address _tokenIn, address _tokenOut, uint256 _amountIn) public checking_amount(_tokenIn, _amountIn) { 182 | IERC20(_tokenIn).approve(address(uni_router_v2), _amountIn); 183 | 184 | address[] memory _path = get_path(_tokenIn, _tokenOut); 185 | 186 | uni_router_v2.swapExactTokensForTokensSupportingFeeOnTransferTokens(_amountIn, 0, _path, address(this), block.timestamp + 300); 187 | } 188 | 189 | function uni_v3(address _tokenIn, address _tokenOut, uint256 _amountIn, uint24 _fee) public payable checking_amount(_tokenIn, _amountIn) { 190 | TransferHelper.safeApprove(_tokenIn, address(uni_router_v3), _amountIn); 191 | 192 | ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ 193 | tokenIn: _tokenIn, 194 | tokenOut: _tokenOut, 195 | fee: _fee, 196 | recipient: address(this), 197 | deadline: block.timestamp + 300, 198 | amountIn: _amountIn, 199 | amountOutMinimum: 0, 200 | sqrtPriceLimitX96: 0 201 | }); 202 | 203 | uni_router_v3.exactInputSingle(params); 204 | } 205 | 206 | function arb_swap(address _asset01, address _asset02, uint256 _amount, uint8 _dex_path, uint24 _fee) public { 207 | require(_dex_path < 6, "Invalid dex option for an arbitrage!"); 208 | if (DEX_PATH.UNIV3_UNIV2 == DEX_PATH(_dex_path)) { 209 | require((_fee == 500) || (_fee == 3000) || (_fee == 10000), "Invalid fee for swapping in UniV3"); 210 | uni_v3(_asset01, _asset02, _amount, _fee); 211 | uni_v2(_asset02, _asset01, IERC20(_asset02).balanceOf(address(this))); 212 | } else if (DEX_PATH.UNIV2_UNIV3 == DEX_PATH(_dex_path)) { 213 | require((_fee == 500) || (_fee == 3000) || (_fee == 10000), "Invalid fee for swapping in UniV3"); 214 | uni_v2(_asset01, _asset02, _amount); 215 | uni_v3(_asset02, _asset01, IERC20(_asset02).balanceOf(address(this)), _fee); 216 | } 217 | } 218 | 219 | function fn_RequestFlashLoan(address _token, uint256 _amount, uint8 dex_path) public { 220 | address receiverAddress = address(this); 221 | address asset = _token; 222 | uint256 amount = _amount; 223 | bytes memory params = ""; 224 | uint16 referralCode = 0; 225 | arb_swap_path = dex_path; 226 | 227 | POOL.flashLoanSimple( 228 | receiverAddress, 229 | asset, 230 | amount, 231 | params, 232 | referralCode 233 | ); 234 | } 235 | 236 | function executeOperation( 237 | address asset, 238 | uint256 amount, 239 | uint256 premium, 240 | address initiator, 241 | bytes calldata params 242 | ) external override returns (bool) { 243 | //Logic goes here 244 | uint256 totalAmount = amount + premium; 245 | IERC20(asset).approve(address(POOL), totalAmount); 246 | arb_swap(asset, address(weth), amount, arb_swap_path, 3000); 247 | return true; 248 | } 249 | 250 | function _flashloan(address[] memory assets, uint256[] memory amounts) internal { 251 | address receiverAddress = address(this); 252 | 253 | uint256[] memory modes = new uint256[](assets.length); 254 | 255 | // 0 = no debt (flash), 1 = stable, 2 = variable 256 | for (uint256 i = 0; i < assets.length; i++) { 257 | modes[i] = 0; 258 | } 259 | 260 | address onBehalfOf = address(this); 261 | bytes memory params = ""; 262 | uint16 referralCode = 0; 263 | 264 | POOL.flashLoan( 265 | receiverAddress, 266 | assets, 267 | amounts, 268 | modes, 269 | onBehalfOf, 270 | params, 271 | referralCode 272 | ); 273 | } 274 | 275 | function close() public payable onlyOwner { 276 | selfdestruct(payable(address(this))); 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /smartcontract/contracts/NormalArbitrage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | import "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/Ownable.sol"; 5 | import { IERC20 } from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol"; 6 | import { SafeMath } from "@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeMath.sol"; 7 | import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol'; 8 | //import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Pair.sol'; 9 | import '@uniswap/lib/contracts/libraries/Babylonian.sol'; 10 | 11 | interface IWETH9 { 12 | function withdraw(uint wad) external; 13 | } 14 | 15 | interface IPancakeRouter01 { 16 | function factory() external pure returns (address); 17 | 18 | function WETH() external pure returns (address); 19 | 20 | function addLiquidity( 21 | address tokenA, 22 | address tokenB, 23 | uint256 amountADesired, 24 | uint256 amountBDesired, 25 | uint256 amountAMin, 26 | uint256 amountBMin, 27 | address to, 28 | uint256 deadline 29 | ) 30 | external 31 | returns ( 32 | uint256 amountA, 33 | uint256 amountB, 34 | uint256 liquidity 35 | ); 36 | 37 | function addLiquidityETH( 38 | address token, 39 | uint256 amountTokenDesired, 40 | uint256 amountTokenMin, 41 | uint256 amountETHMin, 42 | address to, 43 | uint256 deadline 44 | ) 45 | external 46 | payable 47 | returns ( 48 | uint256 amountToken, 49 | uint256 amountETH, 50 | uint256 liquidity 51 | ); 52 | 53 | function removeLiquidity( 54 | address tokenA, 55 | address tokenB, 56 | uint256 liquidity, 57 | uint256 amountAMin, 58 | uint256 amountBMin, 59 | address to, 60 | uint256 deadline 61 | ) external returns (uint256 amountA, uint256 amountB); 62 | 63 | function removeLiquidityETH( 64 | address token, 65 | uint256 liquidity, 66 | uint256 amountTokenMin, 67 | uint256 amountETHMin, 68 | address to, 69 | uint256 deadline 70 | ) external returns (uint256 amountToken, uint256 amountETH); 71 | 72 | function removeLiquidityWithPermit( 73 | address tokenA, 74 | address tokenB, 75 | uint256 liquidity, 76 | uint256 amountAMin, 77 | uint256 amountBMin, 78 | address to, 79 | uint256 deadline, 80 | bool approveMax, 81 | uint8 v, 82 | bytes32 r, 83 | bytes32 s 84 | ) external returns (uint256 amountA, uint256 amountB); 85 | 86 | function removeLiquidityETHWithPermit( 87 | address token, 88 | uint256 liquidity, 89 | uint256 amountTokenMin, 90 | uint256 amountETHMin, 91 | address to, 92 | uint256 deadline, 93 | bool approveMax, 94 | uint8 v, 95 | bytes32 r, 96 | bytes32 s 97 | ) external returns (uint256 amountToken, uint256 amountETH); 98 | 99 | function swapExactTokensForTokens( 100 | uint256 amountIn, 101 | uint256 amountOutMin, 102 | address[] calldata path, 103 | address to, 104 | uint256 deadline 105 | ) external returns (uint256[] memory amounts); 106 | 107 | function swapTokensForExactTokens( 108 | uint256 amountOut, 109 | uint256 amountInMax, 110 | address[] calldata path, 111 | address to, 112 | uint256 deadline 113 | ) external returns (uint256[] memory amounts); 114 | 115 | function swapExactETHForTokens( 116 | uint256 amountOutMin, 117 | address[] calldata path, 118 | address to, 119 | uint256 deadline 120 | ) external payable returns (uint256[] memory amounts); 121 | 122 | function swapTokensForExactETH( 123 | uint256 amountOut, 124 | uint256 amountInMax, 125 | address[] calldata path, 126 | address to, 127 | uint256 deadline 128 | ) external returns (uint256[] memory amounts); 129 | 130 | function swapExactTokensForETH( 131 | uint256 amountIn, 132 | uint256 amountOutMin, 133 | address[] calldata path, 134 | address to, 135 | uint256 deadline 136 | ) external returns (uint256[] memory amounts); 137 | 138 | function swapETHForExactTokens( 139 | uint256 amountOut, 140 | address[] calldata path, 141 | address to, 142 | uint256 deadline 143 | ) external payable returns (uint256[] memory amounts); 144 | 145 | function quote( 146 | uint256 amountA, 147 | uint256 reserveA, 148 | uint256 reserveB 149 | ) external pure returns (uint256 amountB); 150 | 151 | function getAmountOut( 152 | uint256 amountIn, 153 | uint256 reserveIn, 154 | uint256 reserveOut 155 | ) external pure returns (uint256 amountOut); 156 | 157 | function getAmountIn( 158 | uint256 amountOut, 159 | uint256 reserveIn, 160 | uint256 reserveOut 161 | ) external pure returns (uint256 amountIn); 162 | 163 | function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); 164 | 165 | function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); 166 | } 167 | 168 | interface IPancakeRouter02 is IPancakeRouter01 { 169 | function removeLiquidityETHSupportingFeeOnTransferTokens( 170 | address token, 171 | uint256 liquidity, 172 | uint256 amountTokenMin, 173 | uint256 amountETHMin, 174 | address to, 175 | uint256 deadline 176 | ) external returns (uint256 amountETH); 177 | 178 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 179 | address token, 180 | uint256 liquidity, 181 | uint256 amountTokenMin, 182 | uint256 amountETHMin, 183 | address to, 184 | uint256 deadline, 185 | bool approveMax, 186 | uint8 v, 187 | bytes32 r, 188 | bytes32 s 189 | ) external returns (uint256 amountETH); 190 | 191 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 192 | uint256 amountIn, 193 | uint256 amountOutMin, 194 | address[] calldata path, 195 | address to, 196 | uint256 deadline 197 | ) external; 198 | 199 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 200 | uint256 amountOutMin, 201 | address[] calldata path, 202 | address to, 203 | uint256 deadline 204 | ) external payable; 205 | 206 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 207 | uint256 amountIn, 208 | uint256 amountOutMin, 209 | address[] calldata path, 210 | address to, 211 | uint256 deadline 212 | ) external; 213 | } 214 | 215 | contract NormalArbitrage is Ownable { 216 | using SafeMath for uint256; 217 | 218 | uint256 private constant DEADLINE = 300; 219 | 220 | /* BSC */ 221 | //address private constant PANCAKE_ROUTER_ADDRESS = 0x10ED43C718714eb63d5aA57B78B54704E256024E; 222 | //address private constant SUSHISWAP_ROUTER_ADDRESS = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506; 223 | //address private constant WETH_ADDRESS = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c; // WBNB on Binance Smart Chain 224 | 225 | /* BSC testnet */ 226 | address private constant PANCAKE_ROUTER_ADDRESS = 0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3; 227 | address private constant SUSHISWAP_ROUTER_ADDRESS = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506; 228 | address private constant WETH_ADDRESS = 0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd; // WBNB on Binance Smart Chain 229 | 230 | IPancakeRouter02 private pancakeRouter; 231 | IUniswapV2Router02 private sushiRouter; 232 | IWETH9 private weth; 233 | 234 | constructor() { 235 | pancakeRouter = IPancakeRouter02(PANCAKE_ROUTER_ADDRESS); 236 | sushiRouter = IUniswapV2Router02(SUSHISWAP_ROUTER_ADDRESS); 237 | weth = IWETH9(WETH_ADDRESS); 238 | } 239 | 240 | // Events 241 | event Received(address sender, uint256 value); 242 | event Withdraw(address to, uint256 value); 243 | event Minner_fee(uint256 value); 244 | event Withdraw_token(address to, uint256 value); 245 | 246 | receive() external payable {} 247 | 248 | fallback() external payable {} 249 | 250 | /*function withdraw(uint256 _amount) public onlyOwner returns (bool) { 251 | require(_amount <= address(this).balance, "Insufficient ETH amount!"); 252 | payable(msg.sender).transfer(_amount); 253 | 254 | emit Withdraw(msg.sender, _amount); 255 | return true; 256 | } 257 | 258 | function withdrawWeth(uint8 _percentage) public onlyOwner returns (bool) { 259 | require(IERC20(WETH_ADDRESS).balanceOf(address(this)) > 0, "There is no WETH balance!"); 260 | require((0 < _percentage) && (_percentage <= 100), "Invalid percentage!"); 261 | 262 | weth.withdraw(IERC20(WETH_ADDRESS).balanceOf(address(this))); 263 | 264 | uint256 amount_to_withdraw = SafeMath.mul(SafeMath.div(address(this).balance, 100), _percentage); 265 | block.coinbase.transfer(amount_to_withdraw); 266 | emit Minner_fee(amount_to_withdraw); 267 | 268 | return withdraw(address(this).balance); 269 | }*/ 270 | 271 | function withdrawToken(address _token) public onlyOwner returns (bool) { 272 | uint256 balance = IERC20(_token).balanceOf(address(this)); 273 | require(balance > 0, "There is no token balance!"); 274 | bool check = IERC20(_token).transfer(msg.sender, balance); 275 | 276 | emit Withdraw_token(msg.sender, balance); 277 | return check; 278 | } 279 | 280 | /*function swapTokenWithWethOnPancakeswap(address token, uint256 amount) external { 281 | address[] memory path = new address[](2); 282 | path[0] = token; 283 | path[1] = WETH_ADDRESS; 284 | 285 | IERC20(token).approve(address(pancakeRouter), amount); 286 | pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 287 | amount, 288 | 0, 289 | path, 290 | address(this), 291 | block.timestamp + DEADLINE 292 | ); 293 | } 294 | 295 | function swapTokensOnPancakeswap(address tokenIn, address tokenOut, uint256 amountIn) external { 296 | address[] memory path = new address[](2); 297 | path[0] = tokenIn; 298 | path[1] = tokenOut; 299 | 300 | IERC20(tokenIn).approve(address(pancakeRouter), amountIn); 301 | uint[] memory amounts = pancakeRouter.getAmountsOut(amountIn, path); 302 | 303 | //IERC20(tokenOut).approve(address(pancakeRouter), amounts[amounts.length - 1]); 304 | pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 305 | amountIn, 306 | amounts[amounts.length - 1], 307 | path, 308 | address(this), 309 | block.timestamp + DEADLINE 310 | ); 311 | } 312 | 313 | function swapTokenWithWethOnSushiswap(address token, uint256 amount) external { 314 | address[] memory path = new address[](2); 315 | path[0] = token; 316 | path[1] = WETH_ADDRESS; 317 | 318 | IERC20(token).approve(address(sushiRouter), amount); 319 | sushiRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 320 | amount, 321 | 0, 322 | path, 323 | address(this), 324 | block.timestamp + DEADLINE 325 | ); 326 | } 327 | 328 | function swapTokensOnSushiswap(address tokenIn, address tokenOut, uint256 amountIn) external { 329 | address[] memory path = new address[](2); 330 | path[0] = tokenIn; 331 | path[1] = tokenOut; 332 | 333 | IERC20(tokenIn).approve(address(sushiRouter), amountIn); 334 | uint256[] memory amounts = sushiRouter.getAmountsOut(amountIn, path); 335 | 336 | sushiRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 337 | amountIn, 338 | amounts[amounts.length - 1], 339 | path, 340 | address(this), 341 | block.timestamp + DEADLINE 342 | ); 343 | }*/ 344 | 345 | function trade(address token0, address token1, uint256 amount, bool firstPancake) external { 346 | address[] memory path = new address[](2); 347 | 348 | if (firstPancake) { 349 | /* Swap using Pancakeswap */ 350 | path[0] = token0; 351 | path[1] = token1; 352 | 353 | IERC20(token0).approve(address(pancakeRouter), amount); 354 | //uint256[] memory amounts = pancakeRouter.getAmountsOut(amount, path); 355 | pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 356 | amount, 357 | 0,//amounts[amounts.length - 1], 358 | path, 359 | address(this), 360 | block.timestamp + DEADLINE 361 | ); 362 | 363 | /* Swap using Sushiswap */ 364 | path[0] = token1; 365 | path[1] = token0; 366 | 367 | uint256 amount2 = IERC20(token1).balanceOf(address(this)); 368 | IERC20(token1).approve(address(sushiRouter), amount2); 369 | sushiRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 370 | amount2, 371 | 0, 372 | path, 373 | address(this), 374 | block.timestamp + DEADLINE 375 | ); 376 | } 377 | else { 378 | /* Swap using Sushiswap */ 379 | path[0] = token0; 380 | path[1] = token1; 381 | 382 | IERC20(token0).approve(address(sushiRouter), amount); 383 | //uint256[] memory amounts = sushiRouter.getAmountsOut(amount, path); 384 | sushiRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 385 | amount, 386 | 0,//amounts[amounts.length - 1], 387 | path, 388 | address(this), 389 | block.timestamp + DEADLINE 390 | ); 391 | 392 | /* Swap using Pancakeswap */ 393 | path[0] = token1; 394 | path[1] = token0; 395 | 396 | uint256 amount2 = IERC20(token1).balanceOf(address(this)); 397 | IERC20(token1).approve(address(pancakeRouter), amount2); 398 | pancakeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 399 | amount2, 400 | 0, 401 | path, 402 | address(this), 403 | block.timestamp + DEADLINE 404 | ); 405 | } 406 | } 407 | } 408 | -------------------------------------------------------------------------------- /smartcontract/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomicfoundation/hardhat-chai-matchers") 2 | require("@nomiclabs/hardhat-ethers"); 3 | require("@nomiclabs/hardhat-etherscan"); 4 | const secrets = require("./secrets.json"); 5 | 6 | const ETHERSCAN_API_KEY = secrets.ether_scan_api_key; 7 | const BSCSCAN_API_KEY = secrets.bsc_scan_api_key; 8 | const PRIVATE_KEY = secrets.private_key; 9 | const PRIVATE_KEY2 = secrets.private_key2; 10 | // const MY_PRIVATE_KEY = secrets.my_private_key2; 11 | 12 | /** @type import('hardhat/config').HardhatUserConfig */ 13 | module.exports = { 14 | solidity: "0.8.10", 15 | networks:{ 16 | goerli: { 17 | url: "https://rpc.goerli.eth.gateway.fm",//"https://goerli.infura.io/v3/f65bf972517c4a60be9ce62a2207d6a8"; //"https://rpc.goerli.eth.gateway.fm" 18 | chainId: 5, 19 | accounts:[PRIVATE_KEY], 20 | }, 21 | bsc: { 22 | url: "https://bsc-dataseed.binance.org/", 23 | chainId: 56, 24 | gasPrice: 20000000000, 25 | accounts: [PRIVATE_KEY], 26 | }, 27 | bscTestnet: { 28 | url: "https://data-seed-prebsc-1-s1.binance.org:8545", 29 | chainId: 97, 30 | gasPrice: 20000000000, 31 | accounts: [PRIVATE_KEY2], 32 | }, 33 | hardhat: { 34 | gasPrice: 10000000000, // Set the gas price to 20 Gwei 35 | // Other configurations... 36 | } 37 | }, 38 | etherscan: { 39 | apiKey: { 40 | goerli: ETHERSCAN_API_KEY, 41 | bsc: BSCSCAN_API_KEY, 42 | bscTestnet: BSCSCAN_API_KEY 43 | } 44 | }, 45 | settings: { 46 | optimizer: { 47 | enabled: true, 48 | runs: 200, 49 | }, 50 | }, 51 | allowUnlimitedContractSize: true, 52 | }; 53 | -------------------------------------------------------------------------------- /smartcontract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "compile": "npx hardhat compile", 4 | "deploy": "npx hardhat run scripts/deployNormal.js --network bscTestnet", 5 | "verify": "npx hardhat verify --network bscTestnet