Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't send any amount of eth, "gas required exceeds allowance or always failing transaction" #21007

Closed
l4zygreed opened this issue Apr 30, 2020 · 8 comments · Fixed by #21043
Closed
Assignees

Comments

@l4zygreed
Copy link

After updating geth to latest version, can't send any amount of eth

System information

Geth version: 1.9.13-stable
OS & Version: CentOS 7

Expected behaviour

Could send 0.001-0.0046 eth to another address from account with 0.005 eth

Actual behaviour

Always getting error like
gas required exceeds allowance (%amount%) or always failing transaction

> web3.fromWei(eth.getBalance('0xae6c49f8e7dcd277067fa79422a3b7e7ddb8e368'), 'ether')
0.00505881

> eth.sendTransaction({from: '0xae6c49f8e7dcd277067fa79422a3b7e7ddb8e368', to: '0xe205B0ea9A15538Eb4DDCd40267bf19189B6D23a', value: web3.toWei(0.0015,'ether')})
Error: gas required exceeds allowance (9975503) or always failing transaction
	at web3.js:6347:37(47)
	at web3.js:5081:62(37)
	at <eval>:1:20(15)

eth.estimateGas({from: '0xae6c49f8e7dcd277067fa79422a3b7e7ddb8e368', to: '0xe205B0ea9A15538Eb4DDCd40267bf19189B6D23a', value: web3.toWei(0.0015,'ether')})
21000
@karalabe
Copy link
Member

That seems odd because that error message originates from estimateGas, which seems to run well in your second invocation.

@l4zygreed
Copy link
Author

Seems like this error appears only on accounts where eth amount is under the specific value
I have access to account with 0.2 eth and transactions runs well on it

@holiman
Copy link
Contributor

holiman commented Apr 30, 2020 via email

@l4zygreed
Copy link
Author

Using Ethereum logic I can transfer ~0.0046 eth from account with 0.005 eth and rest will be used as gas.
But I can't transfer even 0.001 eth.
Ethereum guis like mist or metamask doesn't show any errors and they propose to transfer the same amount of eth as I wrote as maximum available to transfer.
So it doesn't seems like account have too low balance.

@karalabe
Copy link
Member

Hmm, @holiman I think this may be a legit bug. If gas estimation uses non-zero gas price (sendTransaction should do that), then binary search can fail if the attempted gas limit is larger than what the account can cover.

@karalabe
Copy link
Member

I think we'd need to add an extra clause to estimateGas, so the max cap is also capped by available balance?

@visopsys
Copy link

FYI, I still have this error after #21043

2020/07/27 15:44:38 gas required exceeds allowance (8000029) or always failing transaction
exit status 1

@visopsys
Copy link

@rjl493456442 Here is the code that I use to send token from a smart contract (some info are obfuscated) but you can reproduce them with your own smart contract & account address.

package main

import (
    "context"
    "crypto/ecdsa"
    "fmt"
    "log"
    "math/big"

    "github.com/miguelmota/go-ethereum-hdwallet"

    ethereum "github.com/ethereum/go-ethereum"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/common/hexutil"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/ethclient"
    "github.com/ethereum/go-ethereum/accounts"
    "golang.org/x/crypto/sha3"
)

const TOKEN_ADDRESS = "0xOBFUSCATED"
const TO_ADDRESS = "0xOBFUSCATED"

func getAccount() (*hdwallet.Wallet, accounts.Account, error) {
    // Metamask test mnemonic
    mnemonic := "0xOBFUSCATED"
    wallet, err := hdwallet.NewFromMnemonic(mnemonic)
    if err != nil {
        log.Fatal(err)
    }

    path := hdwallet.MustParseDerivationPath("OBFUSCATED")
    account, err := wallet.Derive(path, false)
    return wallet, account, err
}

func getPrivateKey() (string, error) {
    wallet, account, err := getAccount()
    if err != nil {
        log.Fatal(err)
    }

    privateKey, err := wallet.PrivateKeyHex(account)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Private key in hex: %s\n", privateKey)
    return privateKey, err
}

func run() {
    client, err := ethclient.Dial("https://ropsten.infura.io/v3/OBFUSCATED")
    if err != nil {
        log.Fatal(err)
    }

    privateKeyHex, err := getPrivateKey()
    privateKey, err := crypto.HexToECDSA(privateKeyHex)
    if err != nil {
        log.Fatal(err)
    }

    publicKey := privateKey.Public()
    publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
    if !ok {
        log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
    }

    fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
    nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("fromAddress = ", fromAddress.Hex())

    value := big.NewInt(0) // in wei (0 eth)
    gasPrice, err := client.SuggestGasPrice(context.Background())
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("gasPrice = ", gasPrice)

    toAddress := common.HexToAddress(TO_ADDRESS)
    tokenAddress := common.HexToAddress(TOKEN_ADDRESS)

    transferFnSignature := []byte("transfer(address,uint256)")
    hash := sha3.NewLegacyKeccak256()
    hash.Write(transferFnSignature)
    methodID := hash.Sum(nil)[:4]
    fmt.Println(hexutil.Encode(methodID)) // 0xa9059cbb

    paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32)
    fmt.Println(hexutil.Encode(paddedAddress)) 

    amount := new(big.Int)
    amount.SetString("1000000000000000000", 10) // sets the value to 1000 tokens, in the token denomination

    paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)
    fmt.Println(hexutil.Encode(paddedAmount)) 

    var data []byte
    data = append(data, methodID...)
    data = append(data, paddedAddress...)
    data = append(data, paddedAmount...)

    fmt.Println("Getting gas limit...")

    gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{
        To:   &tokenAddress,
        Data: data,
    })
    if err != nil {
        log.Fatal(err)
    }
    // gasLimit := uint64(80000)
    fmt.Println("gasLimit = ", gasLimit) 

    tx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data)

    chainID, err := client.NetworkID(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
    if err != nil {
        log.Fatal(err)
    }

    err = client.SendTransaction(context.Background(), signedTx)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("tx sent: %s", signedTx.Hash().Hex())
}

func main() {
    run()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants