I'm trying to estimate gas by calling .estimateGas() on the trade function of the Kyber exchange contract.

    async getGas(inputToken: TokenInfo, outputToken: TokenInfo, walletAddress: string, amountInWei = Utils.toWei(1), minRate: BN) {
        if (amountInWei.lt(toBN(1000))) throw `{${this.name}}.getGas(): The amount ${amountInWei} must be >= 1000.`;

        var contract = this.getContract();
        let ethValue = inputToken.isETH ? amountInWei: Utils.ZERO_BN;
        var tx: ContractSendMethod = contract.methods.trade(inputToken.contractAddress, amountInWei, outputToken.contractAddress, walletAddress, MAX_ALLOWANCE, minRate, Utils.ZERO_ADDRESS); //Utils.getWalletAddress()
        
        debugger;
        var gas = await tx.estimateGas({ from: walletAddress, gas: 10000000000, value: ethValue }); // FAILS HERE
        debugger;
        return toBN(gas);
    }

I tried estimateGas() without parameters, and with (as shown above). I then found in the docs you may have to call approve on the ERC20 contract first, so I did that also (taken from the docs and modified to fit):

async checkAndApproveTokenForTrade(srcToken: TokenInfo, userAddress: string, srcQty: BN) {
        if (!srcToken.abi || srcToken.contractAddress == Tokens.ETH.contractAddress)
            return;
        
        // check existing allowance given to proxy contract
        var srcTokenContract = srcToken.contract;
        let existingAllowance = toBN(await srcTokenContract.methods.allowance(userAddress, KyberExchange.KYBER_RATE_ADDRESS/*IKyberNetworkProxy_ADDRESS*/).call());

        // if zero allowance, just set to MAX_UINT256
        if (existingAllowance.eq(Utils.ZERO_BN)) {
            console.log("Approving KNP contract to max allowance.");
            var result = await srcTokenContract.methods.approve(KyberExchange.KYBER_RATE_ADDRESS, srcQty).call();
        } else if (existingAllowance.lt(srcQty)) {
            // if existing allowance is insufficient, reset to zero, then set to MAX_UINT256
            console.log("Approving KNP contract to zero, then max allowance.");
            result = await srcTokenContract.methods.approve(KyberExchange.KYBER_RATE_ADDRESS, Utils.ZERO_BN).call();
            result = await srcTokenContract.methods.approve(KyberExchange.KYBER_RATE_ADDRESS, srcQty).call();
        }
    }

    async getGas(inputToken: TokenInfo, outputToken: TokenInfo, walletAddress: string, amountInWei = Utils.toWei(1), minRate: BN) {
        if (amountInWei.lt(toBN(1000))) throw `{${this.name}}.getGas(): The amount ${amountInWei} must be >= 1000.`;

        await this.checkAndApproveTokenForTrade(inputToken, walletAddress, amountInWei);

        var contract = this.getContract();
        let ethValue = inputToken.isETH ? amountInWei: Utils.ZERO_BN;
        var tx: ContractSendMethod = contract.methods.trade(inputToken.contractAddress, amountInWei, outputToken.contractAddress, walletAddress, MAX_ALLOWANCE, minRate, Utils.ZERO_ADDRESS); //Utils.getWalletAddress()
        var gas = await tx.estimateGas({ from: walletAddress, gas: 10000000000, value: ethValue }); // STILL FAILS
        return toBN(gas);
    }

These are the transaction args when executing it: enter image description here

  • 1 - A BN that = "34950159783737063"
  • 5 - A BN that = "2762660877769768"

I keep getting "Returned error: gas required exceeds allowance (123965250) or always failing transaction.". I've run out of ideas to fix this. I wish the error was more descriptive on what exactly the issue is. I'm thinking the function itself is most likely throwing errors, but no idea what or why. I'm able to call the exchange contract to get rates, so the rest of the system is working, just not the part estimating the gas.

0

There are 0 answers