Trong quá trình tìm hiểu về các bot thực hiện Arbitrage, mình có tìm được bộ mã nguồn mở Uniswap Arbitrage Analysis thực hiện Arbitrage trên các pair của UniswapV2 trên nền tảng Ethereum. Ý tưởng tác giả về tính lượng đầu vào tối ưu khá hay, code cũng tương đối hoàn chỉnh. Chúng ta cùng nhau đi sâu tìm hiểu bộ mã nguồn mã này cũng như các phần toán học liên quan.
Mục lục
Vấn đề cần giải quyết khi thực hiện Arbitrage trên Uniswap V2
Uniswap là dex phổ biến nhất với hơn 11,000 cặp giao dịch và thanh khoản 2 tỷ đô la (Tính theo năm 2020). Ở đâu có thị trường, ở đó có cơ hội kinh doanh chênh lệch giá.
Trên Uniswap, chúng ta có thể đổi coin A lấy coin D theo một đường nhất định, ví dụ A->B->C->D, A và D cũng có thể là cùng một coin, nghĩa là bạn có thể đổi A lấy A theo một đường nhất định , và nếu may mắn, bạn có thể nhận được số lượng A nhiều hơn so với đầu vào => Đây chính là ăn chênh lệch giá! Vậy làm cách nào để tìm ra con đường như vậy và xác định số tiền đầu vào tối ưu để mang lại lợi nhuận tối đa?
Để thực hiện được 1 chênh lệch giá, chúng ta cần phải giải quyết 3 vấn đề:
- Tìm đường đi tốt nhất từ A->?->?->…->A
- Xác định lượng đầu vào tối ưu
- Cập nhật thông tin lượng dự trữ của từng cặp giao dịch nhanh nhất
Tìm đường đi tốt nhất
Thực tế đây giống như bài toán tìm đường trên cây đồ thị trong đó:
- Mỗi pair tương đương 1 cạnh của 1 đồ thị
- Một pair có 2 token => 2 token này như là 2 đỉnh trong đồ thị
Vậy chúng ta có thể sử dụng thuật toán tìm kiếm chuyên sâu (DFS – Depth First Search). Thực chất đây là thuật toán vét cạn mà thôi, nhưng chúng ta cần giới hạn độ sâu tìm kiếm. Độ sâu tìm kiếm càng lớn thì đường càng dài, và theo đó phí GAS cũng cao. Dưới đây là giả code thể hiện thuật toán, mảng path ban đầu truyền vào sẽ chỉ có tokenIn.
def findArb(pairs, tokenIn, tokenOut, maxHops, currentPairs, path, circles):
for i in range(len(pairs)):
newPath = path.copy()
pair = pairs[i]
if not pair['token0']['address'] == tokenIn['address'] and not pair['token1']['address'] == tokenIn['address']:
continue
if pair['reserve0']/pow(10, pair['token0']['decimal']) < 1 or pair['reserve1']/pow(10, pair['token1']['decimal']) < 1:
continue
if tokenIn['address'] == pair['token0']['address']:
tempOut = pair['token1']
else:
tempOut = pair['token0']
newPath.append(tempOut)
if tempOut['address'] == tokenOut['address'] and len(path) > 2:
c = { 'route': currentPairs, 'path': newPath }
circles.append(c)
elif maxHops > 1 and len(pairs) > 1:
pairsExcludingThisPair = pairs[:i] + pairs[i+1:]
circles = findArb(pairsExcludingThisPair, tempOut, tokenOut, maxHops-1, currentPairs + [pair], newPath, circles)
return circles
Tìm đầu vào tối ưu
Uniswap V2 sử dụng mô hình CFMM – Constant Function Market Maker, một mô hình mà tích tài sản dự trữ là không đổi.
Giả sử có một cặp giao dịch cho đồng xu A và B, dự trữ cho A là R0, dự trữ cho B là R1, bây giờ chúng ta sử dụng Δa số lượng A để giao dịch Δb số lượng B, giả sử phí là (1-r), ta có phương trình sau:
Bây giờ, giả sử chúng ta đã tìm thấy một đường hoán đổi A->B->C->A, làm cách nào để tìm lượng đầu vào tối ưu cho đường này? Bảng dưới là thông tin đầu ra, đầu vào và dự trữ cho các cặp trong đường đi trên:
Đây là một vấn đề tối ưu hóa. Dựa thông tin trên ta có phương trình sau:
Ta tính tiếp f = Δa – Δa‘, sau đó tính đạo hàm f, rồi tính giá trị đạo hàm f bằng 0 ta tìm được điểm tối ưu (Kiến thức cấp 3, điểm đỉnh hoặc đáy là điểm có đạo hàm bằng 0).
Nhưng đây là path (đường đi) đi qua hai đồng coin trung gian, nếu đi qua nhiều hơn thì sao. Chúng ta cần 1 giải pháp chung tính đầu vào tối ưu cho 1 path có độ dài tùy ý.
Xem xét tình huống A->B->C, có thể không có cặp giao dịch trực tiếp từ A đến C, nhưng với B là cầu nối, chúng ta có thể giao dịch A lấy C, chúng ta nói rằng có một nhóm giao dịch ảo cho A và C , chúng ta có thể lấy tham số dự trữ E0, E1 cho nhóm ảo này?
Theo phương trình(1) và (2) ta có:
Thay thế Δb trong (4) vào (5) ta được:
So sánh dạng của (6) với (4) và (5) ta có
Bây giờ chúng ta có các tham số cho nhóm ảo A->C, hãy xem xét đường dẫn A->B->C->A, với nhóm ảo, đường dẫn bây giờ là: A->C->A, chúng ta có thể tính toán thêm tham số cho A->A, giả sử Ea, Eb, nếu như Ea < Eb, thì có một cơ hội kinh doanh chênh lệch giá. Đối với đường dẫn có độ dài tùy ý, chúng ta có thể tính toán Ea, Eb lặp đi lặp lại.
Bây giờ chúng ta có các thông số Ea, Eb đối với nhóm ảo này từ A->A được xây dựng từ đường dẫn đã cho, chúng ta có:
Đây f là lợi nhuận của chúng ta, sau khi biến đổi ta được f theo Δa và sau đó tính đạo hàm của nó ta được:
Giải phương trình f’=0, chúng ta có thể tìm thấy số tiền đầu vào tối ưu:
Sau khi biến đổi ta tính được như sau (Chú ý điều kiện là Eb*r>Ea):
Để có Δb>Δa thì Δa phải thỏa mã điều kiện dưới và optimial amount luôn nhỏ hơn giá trị này:
Bây giờ code để tìm đường mới sẽ thêm phần tính toán số lượng đầu vào tối ưu:
def findArb(pairs, tokenIn, tokenOut, maxHops, currentPairs, path, bestTrades, count=5):
for i in range(len(pairs)):
newPath = path.copy()
pair = pairs[i]
if not pair['token0']['address'] == tokenIn['address'] and not pair['token1']['address'] == tokenIn['address']:
continue
if pair['reserve0']/pow(10, pair['token0']['decimal']) < 1 or pair['reserve1']/pow(10, pair['token1']['decimal']) < 1:
continue
if tokenIn['address'] == pair['token0']['address']:
tempOut = pair['token1']
else:
tempOut = pair['token0']
newPath.append(tempOut)
if tempOut['address'] == tokenOut['address'] and len(path) > 2:
Ea, Eb = getEaEb(tokenOut, currentPairs + [pair])
newTrade = { 'route': currentPairs + [pair], 'path': newPath, 'Ea': Ea, 'Eb': Eb }
if Ea and Eb and Ea < Eb:
newTrade['optimalAmount'] = getOptimalAmount(Ea, Eb)
if newTrade['optimalAmount'] > 0:
newTrade['outputAmount'] = getAmountOut(newTrade['optimalAmount'], Ea, Eb)
newTrade['profit'] = newTrade['outputAmount']-newTrade['optimalAmount']
newTrade['p'] = int(newTrade['profit'])/pow(10, tokenOut['decimal'])
else:
continue
bestTrades = sortTrades(bestTrades, newTrade)
bestTrades.reverse()
bestTrades = bestTrades[:count]
elif maxHops > 1 and len(pairs) > 1:
pairsExcludingThisPair = pairs[:i] + pairs[i+1:]
bestTrades = findArb(pairsExcludingThisPair, tempOut, tokenOut, maxHops-1, currentPairs + [pair], newPath, bestTrades, count)
return bestTrades
Cập nhật thông tin lượng dự trữ của từng cặp giao dịch nhanh nhất
Trong tất cả các tính toán ở trên, chúng ta bắt buộc phải có các dữ liệu R0, R1, R1′, R2, R2′, R3. Đây chính là lượng dự trữ (Reserve) có trong các pool thanh khoản. Vậy làm sao có được dữ liệu này một cách nhanh nhất và mới nhất.
Nếu chúng ta thực hiện trên Ethereum, như chúng ta đã biết thời gian trung bình sinh block mới trên Ethereum khoảng 15 giây. Như vậy trong vòng 15 giây, chúng ta phải thực hiện: Cập nhật lượng dự trữ của từng cặp giao dịch. Sẽ gặp vấn đề khi số lượng các cặp giao dịch (Trading pairs) nhiều:
- Số lượng các cặp giao dịch nhỏ: Có thể thực hiện theo 1 trong 2 cách
- Thực hiện request đồng thời (Batch request) để lấy dữ liệu lượng dự trữ của tất cả các cặp giao dịch
- Viết thêm contract mới hay sử dụng contract Multical để thực hiện 1 request lấy đồng thời dữ liệu lượng dự trữ cho tất cả các cặp giao dịch.
- Số lượng cặp giao dịch lớn: Thì ta nên thực hiện như sau
- Lần đầu tiên sử dụng Batch Request lấy toàn bộ dữ liệu lượng dự trữ của các cặp giao dịch
- Tiếp đó ta lắng nghe các sự kiện (event) từ blockchain, mỗi block mới, nếu có sự kiện như Swap, Sync, Mint, Burn thì cặp nhật lượng dự trữ các cặp liên quan.
Mở rộng: Tính lượng dự trữ pool ảo với phí khác nhau giữa các pool
Như phần trên, chúng ta có 1 route đi qua 2 pool A->B->C, chúng ta chuyển hóa về 1 pool ảo A->C và chúng ta tính dự trữ của pool ảo nào. Nhưng phần trên hai pool đều có cùng mức phí, nhưng thực tế chúng ta cần giao dịch nhiều pool khác nhau với mức phí từng pool khác nhau. Giẳ sử thông tin như dưới:
Khi đó công thức tính Δb như sau:
Tương tự ta có công thức tính Δc:
Trong công thức của Δc, ta thay Δb bằng công thức ở trên và biến đổi chút ta được:
Nhìn dạng thức của Δc phụ thuộc Δa ta dễ dàng suy ra Pool ảo có phí là (1 – k1) và có lượng dự trữ như sau:
Từ công thức này ta tính được pool ảo của các pool với mức phí khác nhau. Như vậy chúng ta chỉ cần sửa chút hàm getEaEb() là có thể áp dụng được.
Mở rộng: Điều kiện để có cơ hội arbitrage
Theo mục Tìm đầu vào tối ưu, để có cơ hội arbitrage thì Δa>0 hoặc Δb>0 => Tức là Eb*r>Ea. Hoặc theo mục Mở rộng: Tính lượng dự trữ pool ảo với phí khác nhau giữa các pool thì E1*k1>E0 tức K1*K2*R1*R2>Ro*R’1, biến đổi lại cho dễ nhìn:
(K1*R1)*(K2*R2)>Ro*R’1
Thử mở rộng cho 3 pool như dưới:
Theo công thức ta có:
E0 = R0*R’1/(R’1 + k2*R1)
E2 = k2*R2*R1/(R’1 + k2*R1)
Ea = E0*R’2/(R’2 + k3*E2)
Eb = k3*R3*E2/(R’2 + k3*E2)
Điều kiện có cơ hội: Eb*k1>Ea => Ta có:
k1*k3*R3*E2 > E0*R’2 ⇔ k1*k3*R3*k2*R2*R1 > R0*R’1*R’2 ⇔ k1*k2*k3*R1*R2*R3 > R0*R’1*R’2
=> Sau khi nhóm lại cho dễ nhìn thì:
(k1*R1)*(k2*R2)*(k3*R3) > R0*R’1*R’2
Theo công thức ta dễ dàng nhận thấy: Điều kiện để có cơ hội là tích các reserve bên output sau khi đã tính phí phải lớn tích các reserve bên input. Vậy ra có công thức tổng quát là:
(k1*R1)*(k2*R2)*(…)*(kn*Rn) > R0*R’1*…*R’(n-1)
Cài đặt Arbitrage trên Uniswap V2
Xem chi tiết mã nguồn được cài đặt
Như vậy với mỗi 15 giây, chúng ta phải làm được 3 việc sau:
- Cập nhật lượng dự trữ cho tất cả các cặp giao dịch
- Thực hiện tìm đường (path) tốt nhất và tính toán đầu vào tối ưu
- Gửi giao dịch tới Blockchain. Chú ý rằng gọi hàm UniswapV2Router02.getAmountsOut() để kiểm tra lại xem giao dịch có thực sự có lợi nhuận hay không trước khi gửi giao dịch tới mạng lưới blockchain.
Tác giả đã cài đặt toàn bộ mã nguồn bằng Python. Chúng ta cùng xem chi tiết mã nguồn.
Chúng ta xem luồng cài đặt của mã nguồn bắt đầu từ hàm main() trong tệp src/main.py:
- B1: Thực hiện load tất cả các pair trong tệp files/pairs.json => Sau đó gọi hàm selectPairs() trong tệp src/common.py để lọc các pair theo mong muốn.
- B2: Lấy lượng dự trữ của tất cả các pair thông qua hàm get_reserves_batch_mt()
- Nếu số lượng pair mà nhỏ hơn 200 => Gọi hàm get_reserves() => Hàm này sẽ tạo ra một batch request để gửi đồng thời lấy dữ liệu của tất cả các pair.
- Nếu lượng pair lớn hơn 200 thì gom 200 pair tạo thành 1 thread mới để lấy dữ liệu => Các thread sẽ chạy song song.
- Trong cài đặt này tác giả có sử dụng biến toàn cục needChangeKey để xác định xem có dùng RPC mới hay không khi RPC hiện tại có vấn đề. Danh sách các node RPC tác giả đặt cấu hình trong tệp src/config.json
- B3: Gọi hàm findArb() để tìm kiếm cơ hội Arbitrage, mặc định sẽ tìm 5 cơ hội tốt nhất. Chi tiết cài đặt khá giống với phần 1 đã nói ở trên. Có hàm getEaEb() có nhiệm vụ tính lượng dữ trữ của cặp thanh khoản ảo A->A, từ đó ta tính được giá trị đầu vào tối ưu.
- B4: Nếu có cơ hội, tiếp theo lấy dữ liệu lượng token A hiện tại của bot đang có bao nhiêu thông qua hàm getBalance()
- B5: Kiểm tra lợi nhuận trả về có lớn hơn lợi nhuận mong muốn tối thiểu minProfit hay không. Giá trị này cấu hình trong tệp src/config.json
- B6: Gọi hàm doTrade() để thực hiện giao dịch. Hàm tính toán gasPrice cao hơn 20% so với trên mạng lưới, đồng thời kiểm tra amountIn với tài sản bot nắm giữ:
- Nếu đủ tiền sẽ dùng tài sản trên bot bằng cách gọi hàm printMoney() => Thực chất gọi hàm printMoney() trong hợp đồng src/contract/contracts/MoneyPrinter.sol
- Nếu không đủ tiền sẽ sử dụng hàm flashPrintMoney() => Thực chất gọi hàm flashPrintMoney() trong hợp đồng src/contract/contracts/MoneyPrinter.sol. Theo như code trong Contract thì khoản vay thực hiện trên DxDy.
- Cả hai hàm này có tính toán để lợi nhuận phải cover được phí Gas => Theo code thì giá ETH đang tính là 360$ (Tức thời điểm code này cũng đã khá lâu rồi), nếu có sử dụng thì phải sửa lại.
Toàn bộ quá trình trên được lặp đi lặp lại liên tục.
Giao dịch thử nghiệm
Tác giả của bộ mã nguồn cũng đã thực hiện 1 giao dịch thử nghiệm (Xem ảnh dưới)
Áp dụng để cài đặt, chạy và triển khai thử nghiệm trên BSC Testnet
Hướng dẫn cài đặt
Ở đây tôi clone về và chạy thử sử dụng python3 trên hệ điều hành Ubuntu 18. Sau thời gian tìm hiểu fix lỗi, tôi đã cài đặt và chạy thử được. Các lệnh cài đặt như sau:
// Tải source code từ github
git clone https://github.com/ccyanxyz/uniswap-arbitrage-analysis.git
cd uniswap-arbitrage-analysis
// Cập nhật và cài đặt một số công cụ cần thiết
pip3 install --upgrade setuptools
pip3 install --user cython
pip3 install --user cytoolz
// Cài đặt thư viện web3
pip3 install web3
// Cài đặt thư viện uniswapv2
git clone https://github.com/asynctomatic/uniswap-v2-py.git
cd uniswap-v2-py
sudo python3 setup.py install
cd ..
// Sửa lại tệp cấu hình
cd src
nano config.json
// Chạy ứng dụng
python3 main.py
Để chạy được bạn phải cấu hình các thông số trong tệp src/config.json, và bạn còn cần phải triển khai contract src/contract/contracts/MoneyPrinter.sol nên mạng lưới Ethereum. Việc này sẽ khá tốn kém. Vì thế chúng ta sẽ tìm cách chạy trên môi trường Testnet tương đương.
Hướng dẫn chạy trên ứng dụng trên BSC-TESTNET
Project này đang sử dụng thư viện uniswapv2 nên sẽ có một số verify đặc thù của UniswapV2, nên khi sử dụng cho BSC-TESTNET sẽ không hoàn hảo được và bạn phải sửa một chút. Các bước thực hiện để chạy trên môi trường BSC-TESTNET như sau:
Bước 1: Triển khai contract MoneyPrinter
Đầu tiên bạn lên Remix tạo tệp MoneyPrinter.sol và copy nội dung dưới vào:
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
interface IERC20 {
function totalSupply() external view returns (uint supply);
function balanceOf(address _owner) external view returns (uint balance);
function transfer(address _to, uint _value) external returns (bool success);
function transferFrom(address _from, address _to, uint _value) external returns (bool success);
function approve(address _spender, uint _value) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint remaining);
function decimals() external view returns(uint digits);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
interface IPancakeSwap {
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}
contract PrintMoney {
address owner;
IPancakeSwap router = IPancakeSwap(0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3);
constructor() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function setOwner(address _newOwner) onlyOwner external {
owner = _newOwner;
}
function approveToken(address token) onlyOwner external {
IERC20 erc20 = IERC20(token);
erc20.approve(address(router), uint(-1)); // usdt six decimal would fail!
}
function printMoney(
address tokenIn,
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
uint256 deadline
) onlyOwner external {
IERC20 erc20 = IERC20(tokenIn);
erc20.transferFrom(msg.sender, address(this), amountIn);
router.swapExactTokensForTokens(amountIn, amountOutMin, path, msg.sender, deadline);
}
}
Chú ý rằng, trong contract này tôi dùng router của PancakeSwap trên BSC Testnet từ bài viết: Thông tin về contract, token một số Dex tự xây dựng trên môi trường Testnet theo cơ chế AMM (Trong mục: PancakeSwap Testnet – AMM on Binance Smart Chain (BSC) Testnet).
Sau khi triển khai contract này qua Remix, ta được địa chỉ: 0x5DaEd9FAFb056519A0B565110Dd0ebC910a4924D
Tiếp theo trên giao diện Remix bạn gọi hàm approveToken() với tham số là địa chỉ của WBNB.
Bước 2: Sửa lại tệp cấu hình config.json
Sau đó ta sửa lại tệp cấu hình config.json như sau:
{
"start": "weth",
"maxHops": 6,
"minProfit": 0.01,
"pairs": "random",
"pair_num": 20,
"network": "bsc-testnet",
"https": [
"https://data-seed-prebsc-1-s1.binance.org:8545/",
"https://data-seed-prebsc-2-s1.binance.org:8545/",
"http://data-seed-prebsc-1-s2.binance.org:8545/",
"http://data-seed-prebsc-2-s2.binance.org:8545/",
"https://data-seed-prebsc-1-s3.binance.org:8545/",
"https://data-seed-prebsc-2-s3.binance.org:8545/"
],
"bsc-testnet": {
"http": "https://data-seed-prebsc-1-s1.binance.org:8545",
"wss": ""
},
"gasnow_tx": "https://api.taichi.network:10001/rpc/public",
"gasnow": "https://gasnow.sparkpool.com/api/v3/gas/price",
"address": "xxxxxxxxxxxxxxxxxxxxx",
"privkey": "xxxxxxxxxxxxxxxxxxxxx",
"printer_sushi": "0x5DaEd9FAFb056519A0B565110Dd0ebC910a4924D",
"printer": {
"bsc-testnet": "0x5DaEd9FAFb056519A0B565110Dd0ebC910a4924D"
},
"weth": {
"bsc-testnet": "0xae13d989dac2f0debff460ac112a837c89baa7cd"
},
"usdt": {
"bsc-testnet": ""
},
"usdc": {
"bsc-testnet": ""
},
"dai": {
"bsc-testnet": ""
},
"ycrv": {
"bsc-testnet": ""
}
}
Trong config này, phần xxxxxxxxxxxxxxxxxxxxx bạn thay bằng địa chỉ và private key của tài khoản bot của bạn nhé. Ở đây kí hiệu ta vẫn dùng weth do tác giả fix trong code, ta chỉ thay địa chỉ weth bằng địa chỉ wbnb trên BSC-TESTNET.
Bước 3: Sửa lại dữ liệu các pair trong files/pairs.json
Bây giờ ta xóa hết nội dung cũ của tệp files/pairs.json và thay bằng nội dung như dưới:
[{"address":"0x5126c1b8b4368c6f07292932451230ba53a6eb7a","reserve0":"489761693205445994655492585","reserve1":"500377511450903654089461485","token0":{"decimal":18,"address":"0x78867bbeef44f2326bf8ddd1941a4439382ef2a7","name":"BUSD Token","symbol":"BUSD"},"token1":{"decimal":18,"address":"0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684","name":"Tether USD","symbol":"USDT"}},{"address":"0x8b4c4cc21865a792eb248ac0db88859e17697ece","reserve0":"160520452704836670346156214","reserve1":"99679975995052124092479","token0":{"decimal":18,"address":"0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684","name":"Tether USD","symbol":"USDT"},"token1":{"decimal":18,"address":"0x8babbb98678facc7342735486c851abd7a0d17ca","name":"Ethereum Token","symbol":"ETH"}},{"address":"0x6a9d99db0bd537f3ac57cbc316a9dd8b11a703ac","reserve0":"158731346097791519102577647","reserve1":"100806516097054957494168","token0":{"decimal":18,"address":"0x78867bbeef44f2326bf8ddd1941a4439382ef2a7","name":"BUSD Token","symbol":"BUSD"},"token1":{"decimal":18,"address":"0x8babbb98678facc7342735486c851abd7a0d17ca","name":"Ethereum Token","symbol":"ETH"}},{"address":"0xaf9399f70d896da0d56a4b2cbf95f4e90a6b99e8","reserve0":"50288757778379726018603135","reserve1":"49727721293523349565147079","token0":{"decimal":18,"address":"0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684","name":"Tether USD","symbol":"USDT"},"token1":{"decimal":18,"address":"0x8a9424745056eb399fd19a0ec26a14316684e274","name":"Dai Token","symbol":"DAI"}},{"address":"0x1ed2ebaeaaf042a58089e0c7622ecd1b64a34753","reserve0":"1143185522368180937195","reserve1":"1750134848","token0":{"decimal":18,"address":"0x71b9f106d8f4ccd32bd5c37f8ea19c4223c0b9d3","name":"MyTokenBigChungus","symbol":"BIG"},"token1":{"decimal":18,"address":"0xf9f93cf501bfadb6494589cb4b4c15de49e85d0e","name":"PancakeSwap Token","symbol":"Cake"}},{"address":"0x8714677f72e6bbff8aad0bb60f9c2dc6d17059c3","reserve0":"1000000000000000000013","reserve1":"6544990573755679650086920","token0":{"decimal":18,"address":"0x33a6be22f2b726fff147d8ecc6d021dd5fde6de4","name":"Ethereum Token","symbol":"ETH"},"token1":{"decimal":18,"address":"0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684","name":"Tether USD","symbol":"USDT"}},{"address":"0xf855e52ecc8b3b795ac289f85f6fd7a99883492b","reserve0":"4817463483642684333826882","reserve1":"11754933525816736113537","token0":{"decimal":18,"address":"0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684","name":"Tether USD","symbol":"USDT"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xdd4bdb1e31c6a5edb0e96e61a05e2664bcde578a","reserve0":"252956121764325870688","reserve1":"2900071","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xf9f93cf501bfadb6494589cb4b4c15de49e85d0e","name":"PancakeSwap Token","symbol":"Cake"}},{"address":"0x3129b45b375a11abf010d2d10db1e3dcf474a13c","reserve0":"228675837498771950223","reserve1":"40801534198826723556","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xdacbdecc2992a63390d108e8507b98c7e2b5584a","name":"SafeMoon","symbol":"SAFEMOON"}},{"address":"0x7f2c809496e8d98b970e66307ca72c46644bfbca","reserve0":"556456422300468872","reserve1":"57857291447016961527","token0":{"decimal":18,"address":"0x71b9f106d8f4ccd32bd5c37f8ea19c4223c0b9d3","name":"MyTokenBigChungus","symbol":"BIG"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x44c8ab0c1baacb297bc1d2bd67c7012eb48e836e","reserve0":"9299178605322735494540","reserve1":"31600651594947765182","token0":{"decimal":18,"address":"0x5bf600fded9c01c57b7218dab09062d5de508f13","name":"bfi.money","symbol":"BFII"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xb27f628c12573594437b180a1ea1542d15e0cb78","reserve0":"7148764607106367632","reserve1":"28056370820659049536","token0":{"decimal":18,"address":"0x8babbb98678facc7342735486c851abd7a0d17ca","name":"Ethereum Token","symbol":"ETH"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xf2dd4f955ee29736fe7a03badce7fc3d858edb09","reserve0":"96161031895553632937","reserve1":"26000058361941627941","token0":{"decimal":9,"address":"0xa4624a1178d75e8345c94324c6f65deb6f3d4663","name":"Sea Token SeaXV2","symbol":"SeaXV2"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xe49914410bff665186a148bcab1294a763f8435c","reserve0":"50241849529883111878677","reserve1":"17781663933395994188","token0":{"decimal":9,"address":"0x6a077c488afa93ac8c02d1f989e3a258424920b5","name":"DOGISTYLE","symbol":"DOGI"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x40a6f287fbf5e1841f76ce0218ff23edcd55f96d","reserve0":"15847843491461327948","reserve1":"21602206033090348635024","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xd3b6a0e47a4907b27b748ce56e53303fbb05cc9b","name":"Token B","symbol":"TKNB"}},{"address":"0x29089e9bdd77ac719bcb94d6ee1ee34f2fee8cf8","reserve0":"65909654691237217588","reserve1":"15182788544069357040","token0":{"decimal":18,"address":"0x43fc744c34b211cd57c6f0d1ddb4ea8bc504541b","name":"BALLEv2","symbol":"BALLE"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x2702f4727b9271ee15d6949a1bb0268fcf7a6f2d","reserve0":"2734849081238344465831","reserve1":"14831712459478458695","token0":{"decimal":9,"address":"0x578d863ef7d4cd53c98fb3511ab4bd6af2d11917","name":"Fibonacci Coin","symbol":"FIBO"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xcadd517e82a46fe8d96f3aa319d95becd8bdd3e5","reserve0":"816685370186167491913426","reserve1":"13696380565670248169","token0":{"decimal":18,"address":"0x9081f0387ea6474220b5d59c040fe8c46c3f9c1f","name":"Xpool","symbol":"XPO"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x3edd0c7cec29179d45431471e413be197fb31446","reserve0":"32163698535794975526749","reserve1":"13220443151244466956","token0":{"decimal":18,"address":"0xac9b54f806af4b9451f1faa5293601d5006348ad","name":"Token A","symbol":"TKNA"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xd4bb134a872e520baef4053be6c41877ba6b92a1","reserve0":"486267315050499004770918","reserve1":"10301658579025041666","token0":{"decimal":9,"address":"0x9b5ed8f4ee41418f6625a8f90cd286899f6eafd2","name":"DumbMoon","symbol":"DumbMoon"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x2347ce960974efd08434741a895d733c96f1ff87","reserve0":"1000000","reserve1":"10000000000000000000","token0":{"decimal":1,"address":"0x3b67243321bc3b51853514003e2f62a3213abf51","name":"Basic Token","symbol":"BTN"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xbca27ea7aa158e9dfeb5fb467042ced3feea526d","reserve0":"9491065820000000000","reserve1":"7264999991","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":2,"address":"0xeb68c68ca08933bfb599d2e47eee499bf85d3b49","name":"MeCoin","symbol":"MEC"}},{"address":"0x5da3508070b5dd7886ed2aa19b8761dc64675263","reserve0":"9029367143280031087","reserve1":"110780000000000000000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xbdafbb26f35f05e904d01d0ff433a4bcfa6a60a0","name":"Somis Market","symbol":"SOMIS"}},{"address":"0x37d053ddc5229c238aa264fd09165ab62ff32720","reserve0":"480937351451166116820276","reserve1":"8343840404784841078","token0":{"decimal":9,"address":"0x15fad546c2212bd97f88460aa02dda2b036a86c1","name":"AL2Dumb","symbol":"AL2Dumb"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x1e3443efc3cf186c72140205415a0db9e2bad679","reserve0":"163209899592956","reserve1":"8016663566790773142","token0":{"decimal":9,"address":"0x282b7928210e7411fc4c7889f129c2939e0765c4","name":"TITIEEEEE","symbol":"tito"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x021ad6ecf9814a0ebcb2b475d385d21dcb44fcb2","reserve0":"776960545267573622581081260911","reserve1":"7987238662712254575","token0":{"decimal":18,"address":"0xa595bda1df84bf473477b2ed6420a73a42da2567","name":"FairGo","symbol":"FGO"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x4178d05bb2c444bd93ec4a53f8ce3160b309a54b","reserve0":"65000000000000000000000000000","reserve1":"6500000000000000000","token0":{"decimal":18,"address":"0x79e7b87adfcd395f103ac0e0de8d65f054ca386c","name":"testdave","symbol":"davet"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x97183353dcd42829fa40fffeacaaf50f77352fb6","reserve0":"143612986127631105072759","reserve1":"6340032944013710534","token0":{"decimal":9,"address":"0x24d5d0b12ae72042f6aeb8ed37e22102ba5816a5","name":"DevShitCoin","symbol":"SH!TD"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xfc9672d3c527bfde548d9ba188df3f0e38f4233e","reserve0":"20448892327796908899459935","reserve1":"6135145927869740240","token0":{"decimal":18,"address":"0x14e28eab7b1146baec135cc90781f0e67e70d1ce","name":"Streets","symbol":"STS"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x1e788a1c3c06875b1519e72b87d5c935859dcce9","reserve0":"77855409198169650034","reserve1":"6100000000000000000","token0":{"decimal":9,"address":"0x252e871bef038b237a578e8653909fc6e9c17f0f","name":"SIMBA V4","symbol":"SMBV4"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xe69359ce451d0a97d052f425eefbab4a04d8a4d3","reserve0":"52725237770613632484227","reserve1":"6050000000000000009","token0":{"decimal":18,"address":"0x54110d71d0df9cce2ef35475136f042cfc5dae92","name":"Hyderabadi","symbol":"HBA"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xcc9ec054e763aeef8f935fdeea05560de69e6a74","reserve0":"6000000000000000000","reserve1":"999999999995000000000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xc8a3ade06a990479d136e14fb9186d932720a466","name":"Secured MoonRat Token","symbol":"SMRAT"}},{"address":"0x0c3a07866c6b655a2e2a168067e9491885f3a7ee","reserve0":"500000000000000000000000","reserve1":"6000000000000000000","token0":{"decimal":9,"address":"0x74a8ff61ec13acc2daad143ad8e5029539db8751","name":"AL3Dumb","symbol":"AL3Dumb"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x4b4b9006ad854f96e79cb3bad65f710128a33f91","reserve0":"16111112000000000000000000","reserve1":"5799999856000011519","token0":{"decimal":18,"address":"0x4ad7ed5eb0ae8d91abbc66e8b86dae7eccd60caf","name":"bingo coin","symbol":"bing"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xf8f7830edb1edbb1e216630adb9d4b36ff9b82c0","reserve0":"87742327285","reserve1":"5700391795446099586","token0":{"decimal":0,"address":"0x0938b47e129c05933b319f795744f0a2396e87d6","name":"LAUK","symbol":"LUK"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x3820f0bbc861841370d36e99bff69f03c1071fe4","reserve0":"115338380523","reserve1":"5550000000000000000","token0":{"decimal":9,"address":"0x3fbfe110c160a95f4d8be4d20760ff2173712f47","name":"GalaxySpeed","symbol":"GLX"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x1f8aa7e8a4d8491361ed95695b24cb92e0de9d9e","reserve0":"9092562284051645753773413348","reserve1":"5500000000000000000","token0":{"decimal":18,"address":"0x4fecd01d5348c22626f6531ccbcfed45a49ec174","name":"NOPAN TOKEN","symbol":"NOPNOP"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x1520964c6a0dd81bdce045de2893cd6a78879f0e","reserve0":"509521037323392970233023","reserve1":"5352507038500627405","token0":{"decimal":9,"address":"0x9b2469d5482ec60029baaeaeca391e685691e328","name":"DevShitCoin2","symbol":"SH!TD"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x1e53c5fa02d7728c9d27851dba7baaeb6449684d","reserve0":"76330780747705019238917","reserve1":"5243093025213922708","token0":{"decimal":18,"address":"0x0a58be90391d7e4e90d06bd3c3b50d55c1e8ae1a","name":"indecoin testnet","symbol":"inc"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xd2761826b1ae18b1e8005bc73c2d1e3c63791555","reserve0":"5235474250321658733","reserve1":"3813860805","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":7,"address":"0xe4cb02ccc2bd5b0f313bebead6e1ad314dd69e57","name":"Donebit","symbol":"DONEBIT"}},{"address":"0x81814af9f0bd78889f83b85e5424c57f9c632200","reserve0":"9000000000000000000000","reserve1":"5215332540000000000","token0":{"decimal":18,"address":"0x00418938a7792b711c0bb7f9944bf4468c1c6cf3","name":"Medcoin","symbol":"MDL"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x1d2431d4b5f7e4c95375e544862087b166d15e30","reserve0":"90000","reserve1":"5136238230000000000","token0":{"decimal":1,"address":"0x7d64115dc369a66ed603dd9082261bdb812809c5","name":"asd","symbol":"DSA"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xccdb6f247a6669fbb8ddd2bca57b381ccfcc0492","reserve0":"9842841816642644759977254","reserve1":"5080391795404204612","token0":{"decimal":9,"address":"0x5ed969739f94668a50cea77dbbe49004316bb2ac","name":"FakeToken","symbol":"FakeToken"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xff4b0756488c45605f3a26fd1035085c556c0334","reserve0":"500000016055347241908","reserve1":"5051516964816412567","token0":{"decimal":9,"address":"0x634b923a12f56c5084e54711d3953ba2fe91f1ff","name":"Riccio","symbol":"Rice"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x8635b8ee6e3ac1b09a9e1bbf6794dcea9afc2cfe","reserve0":"5030000000000000000","reserve1":"119305542483286609400026021","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xf404b91b79da0e72a0a2ebf5dfce847277696804","name":"ICPepe","symbol":"ICP"}},{"address":"0x4dbeaf5147d9373b2e4e7a65add646b630226645","reserve0":"5000000001000000000","reserve1":"499999999900200000019920079996024","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xdfa3a0cda3ec1260168db25dee58130cbecf0aae","name":"SafeBank YES","symbol":"SafeBANK"}},{"address":"0xac630111d6384a5e98f06f8db1ac335e85eff2ae","reserve0":"320000000000000000000000000000000","reserve1":"5000000000000000000","token0":{"decimal":18,"address":"0x6763243cc0ad7c57cdeddea6e82b247100d58f7b","name":"xztoken","symbol":"xzt"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x3f20ee18e9a6d45789aa2791585ab33e2aa9f0d1","reserve0":"80033788487050464506601006488","reserve1":"5000000000000000000","token0":{"decimal":18,"address":"0x21967f1976de47fd0112677dbc9ce7736dde738f","name":"1 Token","symbol":"1TKN"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x208307240ff26cb85e432801edc9452cf5eeb822","reserve0":"180000000000000000000000000","reserve1":"5000000000000000000","token0":{"decimal":18,"address":"0x4e478cc4c6a19fe5ec7311fd79505dbd6366c0fe","name":"TestBerryCoin","symbol":"TBER"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xd25816d629866aa7690089cb978ab3512009826d","reserve0":"51805457834726025326553","reserve1":"4562874051712393626","token0":{"decimal":9,"address":"0xadd028c6325bda319c4f29d774f8d20043274180","name":"NeptuneDeFi","symbol":"NEPT"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x50236ef3dada20df24831366042a8140d12ed140","reserve0":"1000125031257814453613","reserve1":"4446483782932747960","token0":{"decimal":9,"address":"0x0ba1a4823186b4138fe2bff8b1732175c20a56aa","name":"Gaga","symbol":"GAGA"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xd108cfbbf1c72a0f437221c0d632aea2a90abe90","reserve0":"4000001002004258518","reserve1":"3999999000000239999","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xdf8688ae64a81b338f2c219439f71128e0a1bdfc","name":"Infaq Coin V2","symbol":"INFAQ"}},{"address":"0xdc1f0fcc1aea4510902acd5ef6d5bb04a8dd8b23","reserve0":"89861759083785536","reserve1":"3897143450017594759","token0":{"decimal":9,"address":"0x638f1507fe97634598de019bfe5a81ae9b8d598f","name":"Uranus","symbol":"URNS"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x4aeebb2451c68bb5650a4e51210c236cf3390dc1","reserve0":"85738782509288368105173","reserve1":"3500000000000000000","token0":{"decimal":18,"address":"0x9da4e18450fcdfde082adf4d10aca0dcab71068c","name":"ibbcoinTest2","symbol":"ibbcoinTest2"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x8b21bc730eb38352c78c8ffc6e0ac908620ca90c","reserve0":"3441044532318146937","reserve1":"4360428631398365690929","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xead910acc8843b958140a3084e74ad6136297d4d","name":"AL1Dumb","symbol":"AL1Dumb"}},{"address":"0xbae76cba3eeb8a976683f4599041d83ebcbb96ca","reserve0":"1383849539695791152738","reserve1":"39531","token0":{"decimal":18,"address":"0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684","name":"Tether USD","symbol":"USDT"},"token1":{"decimal":18,"address":"0xf9f93cf501bfadb6494589cb4b4c15de49e85d0e","name":"PancakeSwap Token","symbol":"Cake"}},{"address":"0x8eb36f0272ac65b84b36aa1980d5f3ec46b008b4","reserve0":"16669465082684468780484","reserve1":"3136312711909910622","token0":{"decimal":18,"address":"0xa6d6240e5d5b6232996d58b6b3c4555c824dea73","name":"CAKE","symbol":"CAKE"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x602cfcd40cab1dc181e619851555ee4dd6027cfb","reserve0":"3050949356339798241","reserve1":"590000000000000000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xe6dcaf3e11aab3fc333020fcb9915cbe8083036f","name":"TTice","symbol":"TTice"}},{"address":"0x71152d154ac8a802bdc65f90d303b80a5a6dc36b","reserve0":"494000000000000000000000","reserve1":"3036510562132097805","token0":{"decimal":9,"address":"0x4cce41ed8501025ac3316469c663749c5957a27d","name":"TTE123","symbol":"TTE123"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xca09ddd7be864bcc71d2a12a38335fdea110e77b","reserve0":"3036510562132097805","reserve1":"494000000000000000000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xceb474a5c61b890a91b8b3a9e0a970e059170126","name":"TCA123","symbol":"TCA123"}},{"address":"0x5b67fe5d857898ebc0666cb5f5c93a2662f8a9b1","reserve0":"119355925853480833246470778","reserve1":"3018000000000000000","token0":{"decimal":18,"address":"0x8dc1ecca3d81a6a5291aa3daa4894fdc1ea281dc","name":"ICPepe","symbol":"ICP"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x64148df5ef7b33bc1ea93867c3ad63059c2896d1","reserve0":"498000000000000000000000","reserve1":"3012072337445976290","token0":{"decimal":9,"address":"0x531efa24a405f1d5b03c5fd2e240eb03b04c52a6","name":"TTI123","symbol":"TTI123"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x36cd2af35754b27d7b2a8ecf4cd7c034e87ce8b1","reserve0":"3000174482267199140","reserve1":"99999990299999970899","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":8,"address":"0xe2e80b11349a3c11a01e9f1183be45e7d482decc","name":"LIBER8","symbol":"LIBER8"}},{"address":"0xec6ff033e88a4a134744e29600b6db11d47e2731","reserve0":"3000000000000000000","reserve1":"1000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xeaeed04f3ee5b0e78347995aa92308e3078e57e8","name":"NashCoin","symbol":"NashC"}},{"address":"0x9ad20023e99a70436c8407c6989d120f3f70009e","reserve0":"1000000000000","reserve1":"3000000000000000000","token0":{"decimal":0,"address":"0xa43a641f91616e2008cd288332c5cc75925d1c0e","name":"Glue Token","symbol":"GlueTest"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x61aa3679ac0ccfd4c767cabb8205291e9a7fe5ba","reserve0":"2955954675000000000","reserve1":"37752041847170852320330","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xe57aee15f4d2807196bf29ff555a897425e29418","name":"Henek","symbol":"TBN"}},{"address":"0xd2d71f8126ac6a4380bbec4b9e7f8c8a1cd353cf","reserve0":"695000000000000000000000","reserve1":"2879465466523297268","token0":{"decimal":18,"address":"0x1509b318eb53d34d22610db611dc366b17a95b5b","name":"bPOCTEST2","symbol":"bPOCTEST2"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xab77c41646a821353ce7425abb246815d795fcc2","reserve0":"704879855764978525169902","reserve1":"2839108981147711955","token0":{"decimal":18,"address":"0x33c6de4449c211b14ff417465067a58ada4be30c","name":"bPOCTEST2","symbol":"bPOCTEST2"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xde1714d1344a860e5834b0259f9ffb1a150dcf52","reserve0":"2509951071805390154","reserve1":"99619501752106551228736592417","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xc13706ab7cb5c2fb238697a9de5f4424e4600ac7","name":"Mystery","symbol":"MYS"}},{"address":"0xc8646a3b3ddf73cbe3b02e83e1bf3926c85b9226","reserve0":"600000000000000000000","reserve1":"2500000000000000000","token0":{"decimal":9,"address":"0x896a63a45a22944a50a10ba5f167483d08165de4","name":"TTC123","symbol":"TTC123"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x9f61c0957658968d8d9c019a15c018fdd57b3c20","reserve0":"162614111942168286130913786928","reserve1":"2475265904631692463","token0":{"decimal":9,"address":"0x497228ae8c6d23615564c4766ed3f536b5872c43","name":"Abit Pakan Hiu","symbol":"ABIT"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x5b837b914fa85be27855d5b45fe4ab1183f6042c","reserve0":"859759287060616777047255","reserve1":"2327430415398646932","token0":{"decimal":18,"address":"0x60fc2a37dc0ffe5792daa54ac365debb978c9a0c","name":"bPOCTEST2","symbol":"bPOCTEST2"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xc5359e3706ea1643d710cba4120a30154903487f","reserve0":"894812500000000000000000","reserve1":"2237341526499371637","token0":{"decimal":18,"address":"0x8a6670baf7ee651da1d0c26e3a9930afb01599b9","name":"bPOCTEST2","symbol":"bPOCTEST2"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x80e23ad3da1651fb3015a4e44b2f755ac5e76fbf","reserve0":"809966561092816118886504","reserve1":"2200500000000000000","token0":{"decimal":9,"address":"0x11abd895980e7db1a62e5711bb7162da82200a6f","name":"Shitcoin","symbol":"SH!T"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x55b2d52168b7631811cb45f693c6059ff760886c","reserve0":"16133901951180","reserve1":"2120000000000000000","token0":{"decimal":9,"address":"0x730c8d190bdd81f7c7251536e22dfdc29ea17bd0","name":"1337Token","symbol":"1337"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xb58f3f13a5dc8c98033250b64f47abfea0a1ec6e","reserve0":"948852988039190823152630","reserve1":"2108489179454986938","token0":{"decimal":18,"address":"0x4466325e4ae608914e5327ec2e751cab1cf8ef3a","name":"bPOCTEST1","symbol":"bPOCTEST1"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x9cff0c7eb432bf6eae4f585728e987dd6416fafe","reserve0":"2100000000000000000","reserve1":"9524716639679969520906753025","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xcd4756097e552a01bf142578abb062fa82bcc4b8","name":"SafeBank YES","symbol":"SafeBANK"}},{"address":"0xd49ddaec3c05a8dc88c93b2e76c10c9761c8ba12","reserve0":"20001904943327935993904182","reserve1":"2100000000000000000","token0":{"decimal":18,"address":"0x3996b9d0fdc50f546ed89d56dceb49a548f88292","name":"Yes","symbol":"YES"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xe079d26471dd69901e397ae75087600cebceedfd","reserve0":"385540000000000000000000","reserve1":"2075175731166225312","token0":{"decimal":9,"address":"0x4b4a6b85e245654fa24f6b50b67a04f616276a05","name":"TTL123","symbol":"TTL123"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x2ba840b0782c96a34d7ccd360cf2410090fa8a33","reserve0":"587000000000000000000","reserve1":"2044382192143961025","token0":{"decimal":9,"address":"0x865bf0f050525bacd791c5ee9b0acc56cf03b477","name":"TTD123","symbol":"TTD123"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xbf9ebff07f67ab31275d04b40e8a29a20949b8ea","reserve0":"1970501879889286613572","reserve1":"2030000000000000000","token0":{"decimal":18,"address":"0x81d558030077efb3a84b3eb64d2fdca3771d679c","name":"Yetucoin","symbol":"YETU"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x62d69f7c56fa27d7a6a6a61c32fb9a9f885bacde","reserve0":"2023444765222694437","reserve1":"285165453460838423923","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xb2fc734398e021eb5f476a862643488022da5e0e","name":"The Orion Ring","symbol":"TOR"}},{"address":"0xb1c4ef398fd4e7a24e26c98d2e3acbb2c6ebe3c2","reserve0":"2019999999999999999","reserve1":"1941637456936001912","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xb5e81dded222aab5f989aab375c1c125c52937fd","name":"Gaman","symbol":"GAM"}},{"address":"0xf2d5971c774bee5fea1861d84dd6df671b98c431","reserve0":"3940160718233900","reserve1":"2010121252606222445","token0":{"decimal":9,"address":"0x944b9dd81c69e89d3fa9e6ad565dd82ec4786b4c","name":"ICPepe","symbol":"ICPV3"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x414ee093f4ada1995efc843e4d8a1456b1a331db","reserve0":"2001071052854522883","reserve1":"699879359883615202764138935","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":9,"address":"0xf4a0f9bfc9933e9709927100907a8c9b75cc50ab","name":"FairArrow","symbol":"Arrow"}},{"address":"0x3951edc0fe6614276586f67ec4acc0e0d95b2967","reserve0":"2000400881779562326","reserve1":"499900000000000000000000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xbafa36b476ee5a17b69892a1a1283d85983370a4","name":"Business Factory Token","symbol":"BFACTORY"}},{"address":"0xca1788390e6558d813be9b6c8d97d953eb76a4ae","reserve0":"2000000000000000001","reserve1":"250394024095145156073106714976","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xb5921769dea1470ef28b47feb9399b26e277c08e","name":"boris coin","symbol":"brss"}},{"address":"0xd1170fdf1f8001ae7ad1d64ad8947a322b19df23","reserve0":"2000000000000000000","reserve1":"100000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":5,"address":"0xe2f4f9f144d5eba3114449f9e01f44efd8848bbb","name":"YAMANDUCA","symbol":"YAMAN"}},{"address":"0x1405729cc6b46193dea21bc94ab908acfe7dd893","reserve0":"2000000000000000000","reserve1":"921500000000000000","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":8,"address":"0xc91b8c2c7309bbc2a95c4c0e5dd077b9c759c07c","name":"Project Privy","symbol":"PRVY"}},{"address":"0xe24af47e59f7e6bc6f593a0fb3d5cfade97c0f1a","reserve0":"2093338590047837867370","reserve1":"1970161887774092338","token0":{"decimal":9,"address":"0x6460bfb4d4492e834da48940320dde60ea3d7b18","name":"PU$$YPOP","symbol":"P$P"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x9ff46ca8d6c12d0de3efd232268a276c7bb7d9cc","reserve0":"1187505314562744","reserve1":"1853160628739912469","token0":{"decimal":9,"address":"0x8f4c61371a9c341814619b225c1c64f3eb7133a8","name":"buttcheeks","symbol":"butts"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x37172e204de7e2fba6a8e743171c059e397d67f6","reserve0":"1000000000000000000000000000000","reserve1":"1600000000000000000","token0":{"decimal":18,"address":"0x517e2671725ee2fb63b8122f3dd7cb38689c8b49","name":"t.me/SafeFinanceBSC","symbol":"SAFEF"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x7023175c02d9b2c0c632b378b9ad42a9df41cb2f","reserve0":"39867374534050060133820423","reserve1":"1505000000000000000","token0":{"decimal":18,"address":"0x98d0b48e2a876329c06f22c84e8c2df4bad7d402","name":"Business Factory Token","symbol":"BFACTORY"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xf813a736fe27545b081e9df057a3579162509605","reserve0":"33248391807864196692357","reserve1":"1504841817500000000","token0":{"decimal":18,"address":"0x51ed2813e947769e0d29b312650c912b4cacfa3d","name":"Mon20","symbol":"TPMB"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xb84f67ce97017d9461e804f22083aa14f4a9a76b","reserve0":"899995732257336793828176","reserve1":"1500008100672106396","token0":{"decimal":9,"address":"0x7d4d66900b4d0dfb19ffd781dd0b3910fe3dc9fb","name":"DevShitCoin","symbol":"SH!TD"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x9111affbaa6a0dd998336d17fad9060d2ddf5775","reserve0":"1377500039947","reserve1":"1500000000000000000","token0":{"decimal":9,"address":"0x0664038b62cdba420a164124929b8d8c6ffbe631","name":"helioaster","symbol":"ASTER"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0x6ddd119db44b5fdc0b17d904d0f6554c4eb1135f","reserve0":"1000000000000000000000000000000","reserve1":"1500000000000000000","token0":{"decimal":18,"address":"0x4afdf7bf39e9463226e5917fb6e612ffcaea854e","name":"CumRocket","symbol":"CUMMIES"},"token1":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"}},{"address":"0xb09ca18738f4dacbe65f7e868506dd664df63f51","reserve0":"1290000000000000000","reserve1":"7755632288935353304967","token0":{"decimal":18,"address":"0xae13d989dac2f0debff460ac112a837c89baa7cd","name":"Wrapped BNB","symbol":"WBNB"},"token1":{"decimal":18,"address":"0xd78a7b39d7496cfd1f9a4b1c825705f827a58e5c","name":"Honetcat","symbol":"HCAT"}}]
Dữ liệu trên có 98 pairs được tôi export dữ liệu các pair của PancakeSwap trên BSC Testnet theo đúng định dạng của project này.
Bước 3: Sửa lại chút hàm getBalance
Khi chạy đến đoạn có cơ hội, hệ thống check balance tôi gặp lỗi như sau:
exception: ('Web3.py only accepts checksum addresses. The software that gave you this non-checksum address should be considered unsafe, please file it as a bug on their platform. Try using an ENS name instead. Or, if you must accept lower safety, use Web3.to_checksum_address(lower_case_address).', '0xae13d989dac2f0debff460ac112a837c89baa7cd')
Do thư viện Uniswap có kiểm tra Checksum địa chỉ ví để đảm bảo token an toàn, lỗi này phát sinh do mình sử dụng địa chỉ ví ở dạng chữ thường hết. Ví dụ địa chỉ sau là chuẩn 0x1A8886ec0C208c409d4E791e97EE24BA9d21Ef68 nhưng nếu bạn sử dụng 0x1a8886ec0c208c409d4e791e97ee24ba9d21ef68 thì nó không còn chuẩn nữa vì không khớp checksum. Để không phải đổi lại địa chỉ ví, chúng ta phải sửa một chút để fix lỗi này.
Mở tệp common.py, ở dòng 120 ta sẽ thấy lệnh:
c = w3.eth.contract(address=tokenAddress, abi=erc20abi)
Chúng ta sẽ sửa lại thành:
c = w3.eth.contract(address=Web3.to_checksum_address(tokenAddress), abi=erc20abi)
Bước 4: Chạy ứng dụng
Bây giờ chúng ta dùng lệnh sau để chạy ứng dụng:
python3 main.py
Bạn sẽ thấy giao diện ứng dụng chạy như hình dưới. Bạn đã nhìn thấy đã vào phần lấy balance nhưng không có balance nên ứng dụng không làm gì.
Bây giờ chúng ta chuyển tới bot một ít BNB làm phí và 1 WBNB và chạy lại ứng dụng, xem liệu bot có thực hiện lệnh không? Tôi đã chạy thử hơn 12h nhưng chưa thấy cơ hội gì, các bạn có thể thử.
Chúc các bạn có thể tìm kiếm được các cơ hội và tạo được những bot thực sự kiếm được lợi nhuận!
Trả lời