I just deployed this contract and tried to call the main function 'simulate_txn' but I'm getting this error web3.exceptions.ContractLogicError: execution reverted: PancakeLibrary: INSUFFICIENT_INPUT_AMOUNT
I'm not sure why the contract is seeing my input as 0 when I clearly have 1 (in Wei). The contract only simulates a transaction without sending it to the blockchain.
Contract:
pragma solidity >=0.7.0 <0.9.0;
// SPDX-License-Identifier: UNLICENSED
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function swapExactETHForTokensSupportingFeeOnTransferTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
}
interface IWETH {
function deposit() external payable;
}
contract ReBuy {
struct ExchangeResult {
uint256 expected;
uint256 received;
uint256 gas;
}
function deposit(address token, address exchangeRouterAddress) internal {
IUniswapV2Router02 exchangeRouter = IUniswapV2Router02(exchangeRouterAddress);
address[] memory path = new address[](2);
if (token != exchangeRouter.WETH()) {
path[0] = exchangeRouter.WETH();
path[1] = token;
exchangeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: msg.value}(0, path, address(this), block.timestamp + 20);
}
else {
IWETH(token).deposit{value: msg.value}();
}
}
function exchangeToken(address fromToken, address toToken, address exchangeRouterAddress, uint256 amount) private returns (uint256, uint256, uint256)
{
IUniswapV2Router02 exchangeRouter = IUniswapV2Router02(exchangeRouterAddress);
uint256 expected;
uint256 received;
uint256 gas;
//uint256[] memory gas = new uint256[](2);
address[] memory path = new address[](2);
IERC20 token = IERC20(fromToken);
path[0] = fromToken;
path[1] = toToken;
expected = exchangeRouter.getAmountsOut(amount, path)[1];
token.approve(exchangeRouterAddress, type(uint256).max);
gas = gasleft();
exchangeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(amount, 0, path, address(this), block.timestamp + 20);
gas = gas - gasleft();
token = IERC20(toToken);
received = token.balanceOf(address(this));
return (expected, received, gas);
}
function simulate_txn(address baseToken, address token, address exchangeRouterAddress) public payable returns (uint256, uint256, uint256, uint256, uint256, uint256)
{
IERC20 _baseToken = IERC20(baseToken);
uint256 amount;
ExchangeResult memory tokenRes;
ExchangeResult memory baseTokenRes;
deposit(baseToken, exchangeRouterAddress);
amount = _baseToken.balanceOf(address(this));
(tokenRes.expected, tokenRes.received, tokenRes.gas) = exchangeToken(baseToken, token, exchangeRouterAddress, amount);
(baseTokenRes.expected, baseTokenRes.received, baseTokenRes.gas) = exchangeToken(token, baseToken, exchangeRouterAddress, tokenRes.received);
// Finally return all results
return (tokenRes.expected, tokenRes.received, tokenRes.gas, baseTokenRes.expected, baseTokenRes.received, baseTokenRes.gas);
}
}
Code ran to attempt call:
token = '0x67382a3364b97e09f727afb388fe817de18f7a18' # Feel free to change this to any token as desired
base_token = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c' # WBNB
router_address = '0x10ED43C718714eb63d5aA57B78B54704E256024E' # Pancake Router
deployed_contract = '0xbb0FE931CD8B10B68A1445518b03693Eb3b80458'
deployed_contract_ABI = '[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"exchangeRouterAddress","type":"address"}],"name":"simulate_txn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]'
deployed_contract = web3.toChecksumAddress(deployed_contract )
contract = web3.eth.contract(address=deployed_contract , abi=deployed_contract_ABI )
results = contract.functions.simulate_txn(base_token , token, router_address ).call({"value": 1000000000000000000})
print(results)
read
it needs to be declared asview
orpure
. If your function is yellow on remix it means that it's awrite
(transaction) function, if it's blue it's aread
functionpublic view returns
? Pardon my ignorance I'm brand new in solidity. Can you pls show the correction that needs to be made to achieve the goal -- simulate the txn to return the desired valuesview
makes it read-only It. But tbh your whole code needs to be changed. I'll suggest you read about solidity and start with basic smart contracts. And for quotations on Pancakeswap you should useGetAmountsOut()
orGetAmountsIn()
expected = exchangeRouter.getAmountsOut(amount, path)[1];
from PCS (Untaxed amount of tokens received) - the difference between these two values is used to calc tax.