0

When making a contract transaction using go-ethereum (golang) how can I decode the transaction inputs.

Specifically Given a tx.Data []byte , the contract's contractABI abi.ABI and the method that is being called its methodID string how can I decode tx.Data from hexadecimal to go types ?

I've tried doing abi.Methods[methodID].Inputs.Arguments.UnpackValues(tx.Data) but this always results in an empty slice of values.

Code:

func decodeTxParams(abi abi.ABI, method string, data []byte) ([]interface{}, error) {
    txParams, err := abi.Methods[method].Inputs.UnpackValues(data)
    if err != nil {
        return []interface{}{}, err
    }
    return txParams, nil
}

caller:

func (b *backend) SendTransaction(ctx context.Context, tx *types.Transaction) error {
    err := b.Client.SendTransaction(ctx, tx)
    if err != nil {
        return err
    }

    // update local nonce
    msg, err := tx.AsMessage(types.HomesteadSigner{})
    if err != nil {
        return err
    }
    sender := msg.From()
    b.nonceManager.Lock(sender)
    b.nonceManager.Update(sender, tx.Nonce())
    b.nonceManager.Unlock(sender)

    data := msg.Data()
    method, ok := b.methods[string(data[:4])]
    if !ok {
        method = "unknown"
    }

        txParams, err := decodeTxParams(b.abiMap[string(data[:4])], string(data[:4]), data[4:])

    if err != nil {
        return err
    }

    if err != nil {
        glog.Infof("\n%vEth Transaction%v\n\nInvoking transaction: \"%v\".  \nTransaction Failed: %v\n\n%v\n", strings.Repeat("*", 30), strings.Repeat("*", 30), method, err, strings.Repeat("*", 75))
        return err
    }

    glog.Infof("\n%vEth Transaction%v\n\nInvoking transaction: \"%v\".  Hash: \"%v\". \n\n%v\n", strings.Repeat("*", 30), strings.Repeat("*", 30), method, tx.Hash().String(), strings.Repeat("*", 75))

    return nil
}

1 Answer 1

1
func decodeTxParams(abi abi.ABI, v map[string]interface{}, data []byte) (map[string]interface{}, error) {
    m, err := abi.MethodById(data[:4])
    if err != nil {
        return map[string]interface{}{}, err
    }
    if err := m.Inputs.UnpackIntoMap(v, data[4:]); err != nil {
        return map[string]interface{}{}, err
    }
    return v, nil
}
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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