Could someone help me understand what I'm doing wrong and how to fix this? I am trying to implement an Uniswap bot in Goerli testnet, that will buy or sell tokens with WETH under some circumstances. But I faces with an issue, that happens when the bot has to swap back(there are no issues when it buys tokens with WETH regardless what decimals token is) token(that is not 18 decimals) to WETH. In the main function I initially call the swap function to buy token with WETH like this(ICO_BOT.weth_buy_threshold is a constant ==0.01 WEH):
self.swap_token(token_in,token_out,ICO_BOT.weth_buy_threshold)
and in case of some conditions I want swap token back to WETH:
self.swap_token(token_in, token_out, self.get_token_balance(token_in))
So when I swap the tokens back I get the balance of this token in smart contract and pass it in the swap function.
This is the implementation of swap_token, get_min_amount_to_buy functions and get_balance in Python:
def get_min_amount_to_buy(self,token_in,token_out, amount_to_buy):
try:
res = ICO_BOT.my_contract.functions.getAmountOutMin(token_in,token_out,amount_to_buy).call()
print(f'It should return about {res} of token {token_out} for {amount_to_buy} of {token_in} token')
return res #ICO_BOT.weth_buy_threshold
except web3.exceptions.ContractLogicError:
print(f'Not enough liquidity. Try another pair or another amount')
return None
def swap_token(self,token_in,token_out,amount_to_buy):
if self.get_min_amount_to_buy(token_in,token_out,amount_to_buy) is not None and self.get_min_amount_to_buy(token_in,token_out,amount_to_buy)!=0:
nonce = ICO_BOT.w3.eth.get_transaction_count(ICO_BOT.my_address_in_goeri)
tx = ICO_BOT.my_contract.functions._swap_token(token_in,token_out,amount_to_buy,self.get_min_amount_to_buy(token_in,token_out,amount_to_buy),ICO_BOT.my_contract_address).build_transaction({'nonce':nonce,'gas':ICO_BOT.gas})
signed_tx = ICO_BOT.w3.eth.account.signTransaction(tx, ICO_BOT.private_key)
ICO_BOT.w3.eth.sendRawTransaction(signed_tx.rawTransaction)
else:
print(f'we cannot swap these tokens due to the lack of liquidity')
return None
def get_token_balance(self,token):
return ICO_BOT.my_contract.functions.get_balance_token(token).call()
Solidity code to get min amount to swap and swap function itself.
function _swap_token(address _token_in,address _token_out,uint _amountIn,uint _amountOutMin,address _to) external{
address[] memory path;
if (_token_in==WETH_Goerli || _token_out == WETH_Goerli){
path = new address[](2);
path[0]=_token_in;
path[1] = _token_out;}
else {
path = new address[](3);
path[0] = _token_in;
path[1] = WETH_Goerli;
path[2] = _token_out;
}
IUniswapV2Router(uniswap_goerli).swapExactTokensForTokens(_amountIn, _amountOutMin, path, _to, block.timestamp);
}
function getAmountOutMin(address _tokenIn, address _tokenOut, uint256 _amountIn) external view returns (uint256) {
address[] memory path;
if (_tokenIn == WETH_Goerli || _tokenOut == WETH_Goerli) {
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
} else {
path = new address[](3);
path[0] = _tokenIn;
path[1] = WETH_Goerli;
path[2] = _tokenOut;
}
uint256[] memory amountOutMins = IUniswapV2Router(uniswap_goerli).getAmountsOut(_amountIn, path);
return amountOutMins[path.length -1];}
function get_balance_token(address _token) public view returns(uint){
return ERC20(_token).balanceOf(address(this));
}
Although get_min_amount_to_buy returns (as I can see) the correct amount for to swap both for tokens with 18 decimals and non 18 decimals
It should return about 9946580332182532 of token 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6 for 16619667422237978856 of 0xfDf686FB601A8dcC6865f02Ac4BfA8A2F14578f8 token
- swap is successful
It should return about 9963047159820956 of token 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6 for 24021055262063930508653 of 0xE8905d43d4c545Dd8f693DECABF06B161D61ca5C token
- error during the swap
I'm getting the error:
Fail with error 'UniswapV2: K'
error
Please advice how can I fix this! Thank you in advance!