Search code examples
goethereumsmartcontractsgo-ethereumgeth

ERC-20 Token transfer problem: execution reverted: ERC20: transfer from the zero address


i ve been trying to learn stuff about smart contracts lately, but when i tried to understand how a token transfer works i ve encountered this problem. || execution reverted: ERC20: transfer from the zero address || (ropsten network)

the code:


import (
    "context"
    "crypto/ecdsa"
    "fmt"
    "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"
    "golang.org/x/crypto/sha3"
    "log"
    "math/big"
)

func main() {

    client, err := ethclient.Dial("https://ropsten.infura.io/v3")
    if err != nil {
        panic(err)
    }

    chainID, _ := client.NetworkID(context.Background())

    privateKey, err := crypto.HexToECDSA("280a5fb7d2eef8c7956f4e6754c82a46f30496e43f50be4c8a457ef4e45fb1f4")
    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)
    }

    value := big.NewInt(0)

    toAddress := common.HexToAddress("0x0cFd37C2A1c9d0B8833fFE5a772003a350B5Be3f")

    tokenAddress := common.HexToAddress("0x4f1c3F4D89826f27204769Af1617540c219E3A62")

    transferFnSignature := []byte("transfer(address,uint256)")
    hash := sha3.NewLegacyKeccak256()
    hash.Write(transferFnSignature)

    methodID := hash.Sum(nil)[:4]
    fmt.Println(hexutil.Encode(methodID))

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

    amount := new(big.Int)
    amount.SetString("10000000000000000000", 10)
    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...)

    gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{
        To: &tokenAddress,
        Data: data,
    })
    if err != nil {
        log.Fatal(err)
    }
    gasPrice, err := client.SuggestGasPrice(context.Background())
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(gasLimit)

    tx := types.NewTx(&types.LegacyTx{
        Nonce:    nonce,
        GasPrice: gasPrice,
        Gas:      gasLimit,
        To:       &tokenAddress,
        Value:    value,
        Data:     data,
        V:        nil,
        R:        nil,
        S:        nil,
    })

    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("TOKEN TX SENT! || %s ||", signedTx.Hash().Hex())


}

the token address is my contract address, the fromAddress is my wallet who is holding 10000 of my tokens, and the toAddress is a normal wallet. what am i missing here?


Solution

  • Apparently, the problem was with the gasLimit. I changed the gasLimit to:

    gasLimit := uint64(200000)
    

    and it worked.