0

Getting familiar with the geth client and within some code followed a tutorial (HERE) to transfer tokens from an address. When I check the transaction on EtherScan, it has failed:

https://rinkeby.etherscan.io/tx/0xf53488d996a532ae78080a23c54384c8f58438db02130f039b0e08dacf760f86

Not quite sure how to debug this and would appreciate any pointers on this.

Here is copy of my code

package main

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

    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/crypto/sha3"
    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {

    client, err := ethclient.Dial("https://rinkeby.infura.io")
    if err != nil {
        log.Fatal(err)
    }

    privateKey, err := crypto.HexToECDSA("49be7f9b459942977f07f99653b5b042144baefa092c5ac833d6ec9893a5b8dd")
    if err != nil {
        log.Fatal(err)
    }

    publicKey := privateKey.Public()
    publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
    if !ok {
        log.Fatal("error casting public key to ECDSA")
    }

    fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)

    nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
    if err != nil {
        log.Fatal(err)
    }

    value := big.NewInt(0) // Transfering Tokens doesnt need ETH values

    //gasLimit := uint64(21000)

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

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

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

    transferFnSignature := []byte("transfer(address,uint256")

    hash := sha3.NewKeccak256()

    hash.Write(transferFnSignature)

    methodID := hash.Sum(nil)[:4] // read up go lang slices

    fmt.Println(hexutil.Encode(methodID))

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

    amount := new(big.Int)
    amount.SetString("1000000000000000000000", 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:   &toAddress,
        Data: data,
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(gasLimit)

    /*
        Generate Transation Type
    */

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

    /*
        Signing Tx with Sender's Private Key
    */

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

    /*
        Broadcasting Transaction to Network
    */

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

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

}
  • Perhaps you could share your code. The transaction data doesn't start with the expected function selector. From the tutorial, the function signature is transfer(address,uint256), which is then hashed with keccak256 to get the 4-byte prefix 0xa9059cbb, but your transaction starts with 0x30c48a31. – smarx Jul 16 '18 at 21:13
1

Your function signature is wrong. It's missing a right parenthesis. This line:

transferFnSignature := []byte("transfer(address,uint256")

should be this instead:

transferFnSignature := []byte("transfer(address,uint256)")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.