Reputation: 1
I would like to call SwapExactTokensForTokensSupportingFeeOnTransferTokens
in my contract to swap tokens with a transfer fee, however, the transaction reverts with an error. I have enough balance in the contract when calling the function.
The transaction that failed, which I called from the contract: https://dashboard.tenderly.co/tx/bsc/0xe44eba37baba3705376163d94f5d1051ac7ae9b2017ab9e403bad22f6a4c0577
When I perform the following (similar) transaction on the exchange, it works as expected: https://dashboard.tenderly.co/tx/bsc/0x5ab848527c12e76c6316859bab14a454a329aeade8046418f5dd542bcf1bd691/
With the debugging mode of Tenderly, I determined that the two transactions are similar except for the fact that the transaction in the contract had one additional approval call. Also when I submitted the transaction, a gas estimation error popped up in Remix.
Below is the code snippet of my contract. The other function, SwapExactTokensForTokens
, is working in the contract call as expected. In the contract, SwapFeeOnExternal
and SwapExternal
are called to interact with the PancakeSwap Router
.
pragma solidity >=0.8.14;
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
interface IUniswapV2Router {
function getAmountsOut(uint256 amountIn, address[] memory path) external view returns (uint256[] memory amounts);
function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external returns (uint256[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external returns (uint256[] memory amounts);
}
contract SwapTradeExecution {
address owner;
constructor(){
// Set the owner to the account that deployes the contract
owner = msg.sender;
}
modifier onlyOwner() {
// Only owner can execute some functions
require(msg.sender == owner, "Only the owner is allowed to execute");
_;
}
function swapFeeOn(address router, address _tokenIn, address _tokenOut, uint256 _amount) internal {
// Single swap function for uniswap v2 swap.
IERC20(_tokenIn).approve(router, _amount);
address[] memory path;
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
uint deadline = block.timestamp + 300;
IUniswapV2Router(router).swapExactTokensForTokensSupportingFeeOnTransferTokens(_amount, 0, path, address(this), deadline);
}
function swapExternal(address router, address _tokenIn, address _tokenOut, uint256 _amount, uint256 minAmount) external onlyOwner {
// Single swap function for uniswap v2 swap.
IERC20(_tokenIn).approve(router, _amount);
address[] memory path;
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
uint deadline = block.timestamp + 300;
IUniswapV2Router(router).swapExactTokensForTokens(_amount, minAmount, path, address(this), deadline);
}
function swapFeeOnExternal(address router, address _tokenIn, address _tokenOut, uint256 _amount,uint256 minAmount) external onlyOwner {
// Single swap function for uniswap v2 swap.
IERC20(_tokenIn).approve(router, _amount);
address[] memory path;
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
uint deadline = block.timestamp + 300;
IUniswapV2Router(router).swapExactTokensForTokensSupportingFeeOnTransferTokens(_amount, minAmount, path, address(this), deadline);
}
function tokenBalance(address token) public view returns (uint256) {
IERC20 token = IERC20(token);
return token.balanceOf(address(this));
}
function withdrawFunds(address token) external onlyOwner {
IERC20 token = IERC20(token);
uint balance = token.balanceOf(address(this));
require(balance > 0, "No avaliable fund to withdraw");
token.transfer(msg.sender, balance);
}
}
Upvotes: 0
Views: 3017
Reputation: 11
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external returns (uint256[] memory amounts);
replace to
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline) external;
Upvotes: 1