Summary:
The provided output shows an attempt to perform an arbitrage trade on the Binance Smart Chain (BSC) using a bot. The bot checks the prices of three token pairs: ETH/USDC, ETH/BUSD, and BUSD/USDC. It retrieves the token balances for the specified wallet address (0xf1BA27c6D14e137C9e1097B6a31F763DB45760de) and calculates the potential trade amounts based on the available USDC balance.
However, the bot encounters an issue when executing the arbitrage trade. It checks the balance of ETH (token address: 0x2170Ed0880ac9A755fd29B2688956BD959F933F8) for the wallet and finds that the balance is 0. This leads to an insufficient balance error because the available ETH balance (0) is less than the required amount (2384.130455617401 USDC) for the arbitrage trade.
As a result, the bot logs an error message, skips the arbitrage opportunity due to the insufficient balance, and reports that no profitable arbitrage opportunity was found.
The main problem here is the lack of sufficient ETH balance in the specified wallet to execute the arbitrage trade. To resolve this issue, the wallet should have enough ETH balance to cover the required amount for the trade execution. Additionally, the bot’s logic may need to be adjusted to handle cases where the available balances are insufficient for the intended trades.
“”
(base) mima0000@MacBook-Pro son % python web.py
2024-05-22 16:52:19,757 – INFO – Connected to BSC
2024-05-22 16:52:19,927 – INFO – Current block number: 38940500
2024-05-22 16:52:19,980 – INFO – Starting arbitrage check…
2024-05-22 16:52:23,211 – INFO – Pair 0x539e0EBfffd39e54A0f7E5F8FEc40ade7933A664 – Token0: 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 (Decimals: 18), Token1: 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d (Decimals: 18)
2024-05-22 16:52:23,212 – INFO – Raw price: 3769.2186500961557
2024-05-22 16:52:23,212 – INFO – Adjusted price: 3769.2186500961557
2024-05-22 16:52:25,187 – INFO – Pair 0x7213a321F1855CF1779f42c0CD85d3D95291D34C – Token0: 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 (Decimals: 18), Token1: 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56 (Decimals: 18)
2024-05-22 16:52:25,187 – INFO – Reserves: [2270217901281602855, 8547266914545769731589, 1716367256]
2024-05-22 16:52:25,187 – INFO – Raw price: 3764.9544168075645
2024-05-22 16:52:25,187 – INFO – Adjusted price: 3764.9544168075645
2024-05-22 16:52:26,639 – INFO – Pair 0x22536030B9cE783B6Ddfb9a39ac7F439f568E5e6 – Token0: 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d (Decimals: 18), Token1: 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56 (Decimals: 18)
2024-05-22 16:52:26,639 – INFO – Raw price: 0.9994434430298962
2024-05-22 16:52:26,639 – INFO – Adjusted price: 0.9994434430298962
2024-05-22 16:52:26,639 – INFO – ETH/USDC price: 3769.2186500961557
2024-05-22 16:52:26,639 – INFO – ETH/BUSD price: 3764.9544168075645
2024-05-22 16:52:26,639 – INFO – BUSD/USDC price: 0.9994434430298962
2024-05-22 16:52:27,334 – INFO – Token balance for 0x2170Ed0880ac9A755fd29B2688956BD959F933F8: 0 (Decimals: 18)
2024-05-22 16:52:28,032 – INFO – Token balance for 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d: 2384130455617400710619 (Decimals: 18)
2024-05-22 16:52:28,769 – INFO – Token balance for 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56: 0 (Decimals: 18)
2024-05-22 16:52:28,770 – INFO – ETH balance for 0xf1BA27c6D14e137C9e1097B6a31F763DB45760de: 0
2024-05-22 16:52:28,770 – INFO – USDC balance for 0xf1BA27c6D14e137C9e1097B6a31F763DB45760de: 2384.130455617400710619
2024-05-22 16:52:28,770 – INFO – BUSD balance for 0xf1BA27c6D14e137C9e1097B6a31F763DB45760de: 0
2024-05-22 16:52:30,216 – INFO – Token balance for 0x2170Ed0880ac9A755fd29B2688956BD959F933F8: 0 (Decimals: 18)
2024-05-22 16:52:30,925 – INFO – Token balance for 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d: 2384130455617400710619 (Decimals: 18)
2024-05-22 16:52:32,122 – INFO – Token balance for 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56: 0 (Decimals: 18)
2024-05-22 16:52:33,206 – INFO – ETH balance for 0xf1BA27c6D14e137C9e1097B6a31F763DB45760de: 0.0 ETH (raw: 0)
2024-05-22 16:52:33,206 – INFO – USDC balance for 0xf1BA27c6D14e137C9e1097B6a31F763DB45760de: 2384.130455617401 USDC (raw: 2384130455617400710619)
2024-05-22 16:52:33,206 – INFO – BUSD balance for 0xf1BA27c6D14e137C9e1097B6a31F763DB45760de: 0.0 BUSD (raw: 0)
2024-05-22 16:52:33,206 – INFO – Using USDC balance for arbitrage with initial amount: 2384.130455617401 USDC
2024-05-22 16:52:33,739 – INFO – Prices: 3764.9544168075645, 3769.2186500961557, 0.9994434430298962
2024-05-22 16:52:33,739 – INFO – Trade amounts: 8.976142489122164e+24, 3.3833043675919793e+28, 3.3814213659642135e+28
2024-05-22 16:52:34,829 – INFO – Balance of token 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 for wallet: 0.0 (raw: 0)
2024-05-22 16:52:34,829 – ERROR – Insufficient balance: 0.0 < 2384.130455617401
2024-05-22 16:52:34,829 – INFO – Gas cost estimation failed. Skipping this opportunity.
2024-05-22 16:52:34,829 – INFO – No profitable arbitrage opportunity found.
“”
from web3 import Web3
import json
import time
import logging
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger()
# Connect to BSC
bsc = 'https://bsc-dataseed.binance.org/'
web3 = Web3(Web3.HTTPProvider(bsc))
# Check connection
if web3.is_connected():
logger.info("Connected to BSC")
else:
logger.error("Failed to connect to BSC")
exit()
# Check block number to ensure the node is synced
logger.info(f"Current block number: {web3.eth.block_number}")
# PancakeSwap Router and Factory contract addresses
router_address_v2 = web3.to_checksum_address('0x10ED43C718714eb63d5aA57B78B54704E256024E')
router_address_v3 = web3.to_checksum_address('0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B')
# Load ABIs from JSON files
def load_abi(file_path):
with open(file_path, 'r') as file:
return json.load(file)
router_abi_v2 = load_abi('router_abi_v2.json')
router_abi_v3 = load_abi('router_abi_v3.json')
v2_pair_abi = load_abi('pair_v2_abi.json')
v3_pair_abi = load_abi('pair_v3_abi.json')
erc20_abi = load_abi('erc20_abi.json')
# Initialize contracts
router_contract_v2 = web3.eth.contract(address=router_address_v2, abi=router_abi_v2)
router_contract_v3 = web3.eth.contract(address=router_address_v3, abi=router_abi_v3)
# Token addresses
eth_address = web3.to_checksum_address('0x2170Ed0880ac9A755fd29B2688956BD959F933F8')
usdc_address = web3.to_checksum_address('0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d')
busd_address = web3.to_checksum_address('0xe9e7cea3dedca5984780bafc599bd69add087d56')
# Pair addresses
eth_usdc_pair = web3.to_checksum_address('0x539e0ebfffd39e54a0f7e5f8fec40ade7933a664')
eth_busd_pair = web3.to_checksum_address('0x7213a321F1855CF1779f42c0CD85d3D95291D34C')
busd_usdc_pair = web3.to_checksum_address('0x22536030b9ce783b6ddfb9a39ac7f439f568e5e6')
def get_token_balance(token_address, wallet_address):
token_contract = web3.eth.contract(address=token_address, abi=erc20_abi)
balance = token_contract.functions.balanceOf(wallet_address).call()
decimals = token_contract.functions.decimals().call()
logger.info(f"Token balance for {token_address}: {balance} (Decimals: {decimals})")
return balance
def get_token_decimals(token_address):
token_contract = web3.eth.contract(address=token_address, abi=erc20_abi)
decimals = token_contract.functions.decimals().call()
return decimals
# Function to get token addresses for a pair
def get_pair_tokens(pair_address, abi):
pair_contract = web3.eth.contract(address=pair_address, abi=abi)
token0 = pair_contract.functions.token0().call()
token1 = pair_contract.functions.token1().call()
return token0, token1
# Function to get price from V2 pair contract
def get_price_v2(pair_address, token0_decimals, token1_decimals):
try:
pair_contract = web3.eth.contract(address=pair_address, abi=v2_pair_abi)
reserves = pair_contract.functions.getReserves().call()
reserve0, reserve1 = reserves[0], reserves[1]
price = reserve1 / reserve0
price_adjusted = price * (10 ** (token0_decimals - token1_decimals))
token0, token1 = get_pair_tokens(pair_address, v2_pair_abi)
logger.info(f"Pair {pair_address} - Token0: {token0} (Decimals: {token0_decimals}), Token1: {token1} (Decimals: {token1_decimals})")
logger.info(f"Reserves: {reserves}")
logger.info(f"Raw price: {price}")
logger.info(f"Adjusted price: {price_adjusted}")
return price_adjusted
except Exception as e:
logger.error(f"Error fetching price for pair {pair_address}: {e}")
return None
# Function to get price from V3 pair contract
def get_price_v3(pair_address, token0_decimals, token1_decimals, invert=False):
try:
pair_contract = web3.eth.contract(address=pair_address, abi=v3_pair_abi)
slot0 = pair_contract.functions.slot0().call()
sqrt_price_x96 = slot0[0]
if invert:
price = (2 ** 192) / (sqrt_price_x96 ** 2)
else:
price = (sqrt_price_x96 ** 2) / (2 ** 192)
price_adjusted = price * (10 ** (token0_decimals - token1_decimals))
token0, token1 = get_pair_tokens(pair_address, v3_pair_abi)
logger.info(f"Pair {pair_address} - Token0: {token0} (Decimals: {token0_decimals}), Token1: {token1} (Decimals: {token1_decimals})")
logger.info(f"Raw price: {price}")
logger.info(f"Adjusted price: {price_adjusted}")
return price_adjusted
except Exception as e:
logger.error(f"Error fetching price for pair {pair_address}: {e}")
return None
# Update router address dynamically in the arbitrage function
router_address = None
def estimate_gas_cost(wallet_address, token1, token2, amount_in, private_key, router_address):
try:
token_contract = web3.eth.contract(address=token1, abi=erc20_abi)
balance = token_contract.functions.balanceOf(wallet_address).call()
decimals = token_contract.functions.decimals().call()
balance_adjusted = balance / (10 ** decimals)
logger.info(f"Balance of token {token1} for wallet: {balance_adjusted} (raw: {balance})")
amount_in_adjusted = amount_in / (10 ** decimals)
if balance < amount_in:
logger.error(f"Insufficient balance: {balance_adjusted} < {amount_in_adjusted}")
return None
allowance = token_contract.functions.allowance(wallet_address, router_address).call()
logger.info(f"Allowance of token {token1} for router: {allowance}")
approve_gas = 0
if allowance < amount_in:
nonce = web3.eth.get_transaction_count(wallet_address)
reset_approve_tx = token_contract.functions.approve(router_address, 0).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': nonce,
})
signed_reset_approve_tx = web3.eth.account.sign_transaction(reset_approve_tx, private_key=private_key)
web3.eth.send_raw_transaction(signed_reset_approve_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(signed_reset_approve_tx.hash)
approve_tx = token_contract.functions.approve(router_address, amount_in).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': nonce + 1,
})
signed_approve_tx = web3.eth.account.sign_transaction(approve_tx, private_key=private_key)
web3.eth.send_raw_transaction(signed_approve_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(signed_approve_tx.hash)
logger.info("Updated token allowance for router")
approve_gas = web3.eth.estimate_gas(approve_tx)
logger.info(f"Estimated gas for approval: {approve_gas}")
swap_tx = router_contract_v2.functions.swapExactTokensForTokens(
amount_in, 0, [token1, token2], wallet_address, int(time.time()) + 60 * 10 # adding deadline
).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address) + 2,
})
swap_gas = web3.eth.estimate_gas(swap_tx)
logger.info(f"Estimated gas for swap: {swap_gas}")
total_gas = approve_gas + swap_gas if allowance < amount_in else swap_gas
gas_cost = total_gas * web3.eth.gas_price
logger.info(f"Total estimated gas cost: {web3.from_wei(gas_cost, 'ether')} BNB")
return gas_cost
except Exception as e:
logger.error(f"Error estimating gas cost: {e}")
return None
# Function to monitor and log real-time prices
def monitor_prices():
eth_decimals = get_token_decimals(eth_address)
usdc_decimals = get_token_decimals(usdc_address)
busd_decimals = get_token_decimals(busd_address)
eth_usdc_price = get_price_v3(eth_usdc_pair, eth_decimals, usdc_decimals)
eth_busd_price = get_price_v2(eth_busd_pair, eth_decimals, busd_decimals)
busd_usdc_price = get_price_v3(busd_usdc_pair, busd_decimals, usdc_decimals)
logger.info(f"ETH/USDC price: {eth_usdc_price}")
logger.info(f"ETH/BUSD price: {eth_busd_price}")
logger.info(f"BUSD/USDC price: {busd_usdc_price}")
return eth_usdc_price, eth_busd_price, busd_usdc_price
def log_all_token_balances(wallet_address):
eth_balance = get_token_balance(eth_address, wallet_address)
usdc_balance = get_token_balance(usdc_address, wallet_address)
busd_balance = get_token_balance(busd_address, wallet_address)
logger.info(f"ETH balance for {wallet_address}: {web3.from_wei(eth_balance, 'ether')}")
logger.info(f"USDC balance for {wallet_address}: {web3.from_wei(usdc_balance, 'ether')}")
logger.info(f"BUSD balance for {wallet_address}: {web3.from_wei(busd_balance, 'ether')}")
# Function to calculate potential profit
def calculate_profit(price1, price2, price3, wallet_address, private_key, initial_amount, router_address):
logger.info(f"Prices: {price1}, {price2}, {price3}")
amount1 = initial_amount * price1
amount2 = amount1 * price2
amount3 = amount2 * price3
logger.info(f"Trade amounts: {amount1}, {amount2}, {amount3}")
potential_profit = amount3 - initial_amount
gas_cost = estimate_gas_cost(wallet_address, eth_address, usdc_address, initial_amount, private_key, router_address)
if gas_cost is None:
logger.info("Gas cost estimation failed. Skipping this opportunity.")
return None
net_profit = potential_profit - gas_cost
logger.info(f"Net profit: {net_profit}")
slippage_tolerance = 0.01
minimum_receive = net_profit * (1 - slippage_tolerance)
logger.info(f"Minimum receive after slippage: {minimum_receive}")
return minimum_receive
def execute_trade(token1_address, token2_address, token3_address, wallet_address, private_key, initial_amount):
global router_address
token1_contract = web3.eth.contract(address=token1_address, abi=erc20_abi)
token2_contract = web3.eth.contract(address=token2_address, abi=erc20_abi)
token3_contract = web3.eth.contract(address=token3_address, abi=erc20_abi)
# Check balances of all tokens
token1_balance = get_token_balance(token1_address, wallet_address)
token2_balance = get_token_balance(token2_address, wallet_address)
token3_balance = get_token_balance(token3_address, wallet_address)
logger.info(f"Token1 balance: {token1_balance}")
logger.info(f"Token2 balance: {token2_balance}")
logger.info(f"Token3 balance: {token3_balance}")
eth_balance = web3.eth.get_balance(wallet_address)
if eth_balance < web3.toWei(0.01, 'ether'): # Check if ETH balance is less than 0.01 ETH
if token1_balance >= initial_amount:
# Swap Token1 (USDC) to ETH
swap_tx = router_contract_v2.functions.swapExactTokensForETH(
initial_amount, 0, [token1_address, web3.toChecksumAddress('0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c')], wallet_address, int(time.time()) + 120
).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_swap_tx = web3.eth.account.sign_transaction(swap_tx, private_key=private_key)
swap_tx_hash = web3.eth.send_raw_transaction(signed_swap_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(swap_tx_hash)
logger.info("Swapped Token1 (USDC) to ETH")
elif token2_balance >= initial_amount:
# Swap Token2 (BUSD) to ETH
swap_tx = router_contract_v2.functions.swapExactTokensForETH(
initial_amount, 0, [token2_address, web3.toChecksumAddress('0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c')], wallet_address, int(time.time()) + 120
).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_swap_tx = web3.eth.account.sign_transaction(swap_tx, private_key=private_key)
swap_tx_hash = web3.eth.send_raw_transaction(signed_swap_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(swap_tx_hash)
logger.info("Swapped Token2 (BUSD) to ETH")
else:
logger.error("Insufficient balance in Token1 (USDC) or Token2 (BUSD) to swap to ETH")
return 0
# Approve router to spend token1
approve_tx = token1_contract.functions.approve(router_address, initial_amount).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_approve_tx = web3.eth.account.sign_transaction(approve_tx, private_key=private_key)
approve_tx_hash = web3.eth.send_raw_transaction(signed_approve_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(approve_tx_hash)
logger.info("Approved router to spend Token1")
# Execute first trade: Token1 -> Token2
trade1_tx = router_contract_v2.functions.swapExactTokensForTokens(
initial_amount, 0, [token1_address, token2_address], wallet_address, int(time.time()) + 120
).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_trade1_tx = web3.eth.account.sign_transaction(trade1_tx, private_key=private_key)
trade1_tx_hash = web3.eth.send_raw_transaction(signed_trade1_tx.rawTransaction)
trade1_receipt = web3.eth.wait_for_transaction_receipt(trade1_tx_hash)
logger.info("Executed first trade: Token1 -> Token2")
# Get the balance of Token2 received
token2_amount = get_token_balance(token2_address, wallet_address)
logger.info(f"Token2 amount received: {token2_amount}")
if token2_amount == 0:
logger.error("Received 0 Token2. Aborting arbitrage.")
return 0
# Approve router to spend Token2
approve_tx2 = token2_contract.functions.approve(router_address, token2_amount).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_approve_tx2 = web3.eth.account.sign_transaction(approve_tx2, private_key=private_key)
approve_tx2_hash = web3.eth.send_raw_transaction(signed_approve_tx2.rawTransaction)
web3.eth.wait_for_transaction_receipt(approve_tx2_hash)
logger.info("Approved router to spend Token2")
# Execute second trade: Token2 -> Token3
trade2_tx = router_contract_v2.functions.swapExactTokensForTokens(
token2_amount, 0, [token2_address, token3_address], wallet_address, int(time.time()) + 120
).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_trade2_tx = web3.eth.account.sign_transaction(trade2_tx, private_key=private_key)
trade2_tx_hash = web3.eth.send_raw_transaction(signed_trade2_tx.rawTransaction)
trade2_receipt = web3.eth.wait_for_transaction_receipt(trade2_tx_hash)
logger.info("Executed second trade: Token2 -> Token3")
# Get the balance of Token3 received
token3_amount = get_token_balance(token3_address, wallet_address)
logger.info(f"Token3 amount received: {token3_amount}")
if token3_amount == 0:
logger.error("Received 0 Token3. Aborting arbitrage.")
return 0
# Approve router to spend Token3
approve_tx3 = token3_contract.functions.approve(router_address, token3_amount).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_approve_tx3 = web3.eth.account.sign_transaction(approve_tx3, private_key=private_key)
approve_tx3_hash = web3.eth.send_raw_transaction(signed_approve_tx3.rawTransaction)
web3.eth.wait_for_transaction_receipt(approve_tx3_hash)
logger.info("Approved router to spend Token3")
# Execute third trade: Token3 -> Token1
trade3_tx = router_contract_v2.functions.swapExactTokensForTokens(
token3_amount, 0, [token3_address, token1_address], wallet_address, int(time.time()) + 120
).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_trade3_tx = web3.eth.account.sign_transaction(trade3_tx, private_key=private_key)
trade3_tx_hash = web3.eth.send_raw_transaction(signed_trade3_tx.rawTransaction)
trade3_receipt = web3.eth.wait_for_transaction_receipt(trade3_tx_hash)
logger.info("Executed third trade: Token3 -> Token1")
# Get the final balance of Token1
final_amount = get_token_balance(token1_address, wallet_address)
logger.info(f"Final Token1 amount: {final_amount}")
# Calculate profit
profit = final_amount - initial_amount
logger.info(f"Profit: {profit}")
# Check if the final balance is in ETH and swap back to USDC or BUSD
final_eth_balance = web3.eth.get_balance(wallet_address)
if final_eth_balance > web3.toWei(0.01, 'ether'): # Check if final ETH balance is greater than 0.01 ETH
# Swap ETH back to Token1 (USDC)
swap_tx = router_contract_v2.functions.swapExactETHForTokens(
0, [web3.toChecksumAddress('0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c'), token1_address], wallet_address, int(time.time()) + 120
).build_transaction({
'from': wallet_address,
'value': final_eth_balance,
'gasPrice': web3.eth.gas_price,
'nonce': web3.eth.get_transaction_count(wallet_address),
})
signed_swap_tx = web3.eth.account.sign_transaction(swap_tx, private_key=private_key)
swap_tx_hash = web3.eth.send_raw_transaction(signed_swap_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(swap_tx_hash)
logger.info("Swapped ETH back to Token1 (USDC)")
return profit
def arbitrage(wallet_address, private_key, eth_usdc_pair, eth_busd_pair, busd_usdc_pair):
global router_address
eth_usdc_price, eth_busd_price, busd_usdc_price = monitor_prices()
if not eth_usdc_price or not eth_busd_price or not busd_usdc_price:
logger.error("One of the prices could not be fetched. Skipping this round.")
return
# Log all token balances before arbitrage
log_all_token_balances(wallet_address)
# Check balances for all tokens
eth_balance_raw = get_token_balance(eth_address, wallet_address)
usdc_balance_raw = get_token_balance(usdc_address, wallet_address)
busd_balance_raw = get_token_balance(busd_address, wallet_address)
# Convert raw balances based on token decimals
eth_decimals = get_token_decimals(eth_address)
usdc_decimals = get_token_decimals(usdc_address)
busd_decimals = get_token_decimals(busd_address)
eth_balance = eth_balance_raw / (10 ** eth_decimals)
usdc_balance = usdc_balance_raw / (10 ** usdc_decimals)
busd_balance = busd_balance_raw / (10 ** busd_decimals)
logger.info(f"ETH balance for {wallet_address}: {eth_balance} ETH (raw: {eth_balance_raw})")
logger.info(f"USDC balance for {wallet_address}: {usdc_balance} USDC (raw: {usdc_balance_raw})")
logger.info(f"BUSD balance for {wallet_address}: {busd_balance} BUSD (raw: {busd_balance_raw})")
# Determine which token to use for arbitrage based on available balance
initial_amount_raw = 0
initial_amount = 0
trade_sequence = None
if busd_balance > 0:
initial_amount_raw = busd_balance_raw
initial_amount = busd_balance
logger.info(f"Using BUSD balance for arbitrage with initial amount: {initial_amount} BUSD")
trade_sequence = ('BUSD', busd_address, eth_address, usdc_address)
elif eth_balance > 0:
initial_amount_raw = eth_balance_raw
initial_amount = eth_balance
logger.info(f"Using ETH balance for arbitrage with initial amount: {initial_amount} ETH")
trade_sequence = ('ETH', eth_address, usdc_address, busd_address)
elif usdc_balance > 0:
initial_amount_raw = usdc_balance_raw
initial_amount = usdc_balance
logger.info(f"Using USDC balance for arbitrage with initial amount: {initial_amount} USDC")
trade_sequence = ('USDC', usdc_address, eth_address, busd_address)
else:
logger.error("Insufficient balance for any token")
return
token_used = trade_sequence[1]
token_out_1 = trade_sequence[2]
token_out_2 = trade_sequence[3]
# Refresh allowance if necessary
router_address = router_address_v2 # Use V2 router
token_contract = web3.eth.contract(address=token_used, abi=erc20_abi)
allowance = token_contract.functions.allowance(wallet_address, router_address).call()
nonce = web3.eth.get_transaction_count(wallet_address)
if allowance < initial_amount_raw:
reset_approve_tx = token_contract.functions.approve(router_address, 0).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': nonce,
})
signed_reset_approve_tx = web3.eth.account.sign_transaction(reset_approve_tx, private_key=private_key)
web3.eth.send_raw_transaction(signed_reset_approve_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(signed_reset_approve_tx.hash)
logger.info("Reset token allowance to 0")
nonce += 1
approve_tx = token_contract.functions.approve(router_address, initial_amount_raw).build_transaction({
'from': wallet_address,
'gasPrice': web3.eth.gas_price,
'nonce': nonce,
})
signed_approve_tx = web3.eth.account.sign_transaction(approve_tx, private_key=private_key)
web3.eth.send_raw_transaction(signed_approve_tx.rawTransaction)
web3.eth.wait_for_transaction_receipt(signed_approve_tx.hash)
logger.info("Updated token allowance for router")
# Compare prices for potential arbitrage opportunities
if eth_usdc_price < eth_busd_price:
profit = calculate_profit(eth_usdc_price, eth_busd_price, busd_usdc_price, wallet_address, private_key, initial_amount_raw, router_address)
if profit and profit > 0:
logger.info("Profitable arbitrage opportunity found: ETH/USDC -> ETH/BUSD -> BUSD/USDC")
execute_trade(eth_address, usdc_address, busd_address, wallet_address, private_key, initial_amount_raw)
else:
logger.info("No profitable arbitrage opportunity found.")
elif eth_busd_price < eth_usdc_price:
profit = calculate_profit(eth_busd_price, eth_usdc_price, busd_usdc_price, wallet_address, private_key, initial_amount_raw, router_address)
if profit and profit > 0:
logger.info("Profitable arbitrage opportunity found: ETH/BUSD -> ETH/USDC -> BUSD/USDC")
execute_trade(eth_address, busd_address, usdc_address, wallet_address, private_key, initial_amount_raw)
else:
logger.info("No profitable arbitrage opportunity found.")
else:
logger.info("No profitable arbitrage opportunity found.")
# Log all token balances after arbitrage
log_all_token_balances(wallet_address)
# Main loop
def main():
wallet_address = '0xf1BA27c6D14e137C9e1097B6a31F763DB45760de'
private_key = 'XXXXXXXXXXXXXXXXXXXXXXXXX'
while True:
try:
logger.info("Starting arbitrage check...")
arbitrage(wallet_address, private_key, eth_usdc_pair, eth_busd_pair, busd_usdc_pair)
except Exception as e:
logger.error(f"Error: {e}")
time.sleep(1)
if __name__ == "__main__":
main()
user25183994 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.