¿Cómo enviar correctamente una llamada RPC usando Golang para obtener el propietario del contrato inteligente?

Actualización 12 noviembre 2018

Alguien compartió una solución muy cercana a lo que estaba buscando aquí .

Actualización 10 de noviembre de 2018

Como no puedo lograr esto usando el enfoque de esta pregunta, creé mi propia biblioteca para hacer lo mismo ( enlace ). No se basa en el paquete go-ethereum, sino que usa el net/httppaquete normal para realizar la solicitud JSON RPC.

Todavía me encanta saber qué hice mal en mi enfoque a continuación.


Definiciones :

  • propietario = publicvariable en contrato con addresstipo
  • contract = contrato inteligente que tiene dueño

Esta es la solicitud curl para obtener el propietario de un contrato. Me las arreglé para conseguir el dueño.

curl localhost:8545 -X POST \
--header 'Content-type: application/json' \
--data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"to": "0x_MY_CONTRACT_ADDRESS", "data": "0x8da5cb5b"}, "latest"], "id":1}'

{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000_OWNER"}

Pero cuando trato de replicarlo en Golang (código a continuación), obtuve json: no se puede descomponer la cadena en el valor Go del tipo de error main.response.

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/ethereum/go-ethereum/rpc"
)

func main() {
    client, err := rpc.DialHTTP(os.Getenv("RPC_SERVER"))
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    type request struct {
        To   string `json:"to"`
        Data string `json:"data"`
    }

    type response struct {
        Result string
    }

    req := request{"0x_MY_CONTRACT_ADDRESS", "0x8da5cb5b"}
    var resp response
    if err := client.Call(&resp, "eth_call", req, "latest"); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v\n", resp)
}

¿Qué me perdí aquí?

Resultado Esperado:

Dirección en formato de cadena. P.ej0x3ab17372b25154400738C04B04f755321bB5a94b

P/D: conozco abigen y sé que es mejor y más fácil hacer esto usando abigen. Pero estoy tratando de resolver este problema específico sin usar el método Abigen.

Respuestas (1)

En lugar de

type response struct {
    Result string
}

solo pasa la cadena de resultado

var result string
if err := client.Call(&result, "eth_call", req, "latest")

y analizar la dirección

owner := common.HexToAddress(result)
fmt.Printf("%s\n", owner.Hex())

código completo

package main

import (
    "fmt"
    "log"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/rpc"
)

func main() {
    client, err := rpc.DialHTTP("https://mainnet.infura.io")
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    type request struct {
        To   string `json:"to"`
        Data string `json:"data"`
    }

    var result string

    req := request{"0xcc13fc627effd6e35d2d2706ea3c4d7396c610ea", "0x8da5cb5b"}
    if err := client.Call(&result, "eth_call", req, "latest"); err != nil {
        log.Fatal(err)
    }

    owner := common.HexToAddress(result)
    fmt.Printf("%s\n", owner.Hex()) // 0x281017b4E914b79371d62518b17693B36c7a221e
}