0

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)
4
  • 1
    presently, is not simulating any transaction. It sends the transaction. To make a function read it needs to be declared as view or pure. If your function is yellow on remix it means that it's a write (transaction) function, if it's blue it's a read function
    – Adam Boudj
    Mar 24, 2022 at 4:59
  • @AdamBoudjemaa So declare simulate_txn as public 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 values
    – user96723
    Mar 25, 2022 at 5:10
  • Yes, function view 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 use GetAmountsOut() or GetAmountsIn()
    – Adam Boudj
    Mar 25, 2022 at 6:44
  • Ok, I think the word 'simulate' is confusing my intent. Let's scratch the word simulate. Sorry for the confusion. The code intends to do both, transact (w/out signing) and get quotes. The motive here is to deduce the taxes of a token. - So it sends a dummy txn (w/out signing) to get the number of tokens issued (amount potentially received is taxed) - then it runs a getAmountOut(), ref line: expected = exchangeRouter.getAmountsOut(amount, path)[1]; from PCS (Untaxed amount of tokens received) - the difference between these two values is used to calc tax.
    – user96723
    Mar 26, 2022 at 20:38

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.