11

There is a tool on npm ethereum-input-data-decoder. And yes, i can read input data as hex.

And i hope that i can decode transaction's inputdata using golang. For example 0xa9059cbb00000000000000000000000067f883a42031215622e0b84c96d0e4dca7a3ce810000000000000000000000000000000000000000000000000000000005f5e100

thx.

hundred lee
  • 111
  • 1
  • 1
  • 3

6 Answers6

10

took me a bit of time to figure out that myAbi.Unpack(...) unpacks output of a method or event. In your case (and mine) we want to unpack the inputs. Here is a working code sample

// example of transaction input data
txInput := "0xa5142faa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003"

// load contract ABI
abi, err := abi.JSON(strings.NewReader(myContractAbi))
if err != nil {
    log.Fatal(err)
}

// decode txInput method signature
decodedSig, err := hex.DecodeString(txInput[2:10])
if err != nil {
    log.Fatal(err)
}

// recover Method from signature and ABI
method, err := abi.MethodById(decodedSig)
if err != nil {
    log.Fatal(err)
}

// decode txInput Payload
decodedData, err := hex.DecodeString(txInput[10:])
if err != nil {
    log.Fatal(err)
}

// create strut that matches input names to unpack
// for example my function takes 2 inputs, with names "Name1" and "Name2" and of type uint256 (solidity)
type FunctionInputs struct {
    Name1 *big.Int // *big.Int for uint256 for example
    Name2 *big.Int
}

var data FunctionInputs

// unpack method inputs
err = method.Inputs.Unpack(&data, decodedData)
if err != nil {
    log.Fatal(err)
}

fmt.Println(data)
salanfe
  • 611
  • 4
  • 9
4

This is isn't tested, but it'd be sort of like this:

myAbi, err := abi.JSON(strings.NewReader(abiJsonString))
if err != nil {
    log.Fatal(err)
}

var ifc map[string]interface{}
encodedData := "0x00123..."
err := myApi.Unpack(&ifc, "someMethod", encodedData)
if err != nil {
     log.Fatal(err)
}

You'd also have to iterate through all the ABI methods and plug it into the second argument to the abi.Unpack method to find which method the data belongs to.

Miguel Mota
  • 5,143
  • 29
  • 47
3
    if reader, err := os.Open("token.abi"); err != nil {
        log.Fatal(err)
    } else {
        if tokenAbi, err := abi.JSON(reader); err != nil {
            log.Fatal(err)
        } else {
            encodedData := "a9059cbb00000000000000000000000067f883a42031215622e0b84c96d0e4dca7a3ce810000000000000000000000000000000000000000000000000000000005f5e100"
            decodeData, err := hex.DecodeString(encodedData)
            if err != nil {
                log.Fatal(err)
            }
            // a9059cbb == transfer
            if method, ok := tokenAbi.Methods["transfer"]; ok {
                params, err := method.Inputs.Unpack(decodeData[4:])
                if err != nil {
                    log.Fatal(err)
                }
                log.Println(params)
            }
        }
    }

Saman H. Pasha
  • 327
  • 1
  • 7
1

Here is an example about decode input data and output data

https://gist.github.com/crazygit/9279a3b26461d7cb03e807a6362ec855

crazygit
  • 111
  • 2
1

Since geth is written in go, it makes some sense there's probably an official package for this. Looking into the official go-ethereum library, there's a package called abi there, you might be able to use that.

Nick
  • 188
  • 1
  • 7
1

I think you can try with the solution:

myAbi, err := abi.JSON(strings.NewReader(abiJsonString))
if err != nil {
    log.Fatal(err)
}

var ifc map[string]interface{}
encodedData := "0xa9059cbb00000000000000000000000067f883a42031215622e0b84c96d0e4dca7a3ce810000000000000000000000000000000000000000000000000000000005f5e100"
decodeData, _ := hex.DecodeString(encodedData)
err := myApi.Unpack(&ifc, "someMethod", decodeData[4:])
if err != nil {
     log.Fatal(err)
}
PhanHoc
  • 11
  • 1