如何使用Golang正确发送RPC调用以获取智能合约所有者?

时间:2018-11-10 09:47:39

标签: go ethereum json-rpc smartcontracts go-ethereum

更新

由于我无法使用此问题中的方法来实现此目的,因此我创建了自己的库来执行相同的操作(link)。它不依赖go-ethereum软件包,而是使用常规的net/http软件包执行JSON RPC请求。

我仍然很想知道我在下面的方法中做错了什么。


定义

  • 所有者 = public类型合同中的address变量
  • 合同 =具有所有者
  • 的智能合同

这是获取合同所有者的请求。我设法找到了主人。 (JSON RPC docs

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"}

但是当我尝试在Golang中复制它时(下面的代码),我得到了 json:无法将字符串解组为main.response 类型的Go值错误。 (go-ethereum code that I use

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)
}

我在这里想念什么?

预期结果:

以字符串格式的地址。例如。 0x3ab17372b25154400738C04B04f755321bB5a94b

P / S —我知道abigen,而且我知道使用abigen进行此操作会更好,更容易。但我正在尝试不使用abigen方法来解决此特定问题。

4 个答案:

答案 0 :(得分:2)

您可以使用go-ethereum/ethclient来最好地解决问题:

package main

import (
    "context"
    "log"

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

func main() {
    client, _ := ethclient.Dial("https://mainnet.infura.io")
    defer client.Close()

    contractAddr := common.HexToAddress("0xCc13Fc627EFfd6E35D2D2706Ea3C4D7396c610ea")
    callMsg := ethereum.CallMsg{
        To:   &contractAddr,
        Data: common.FromHex("0x8da5cb5b"),
    }

    res, err := client.CallContract(context.Background(), callMsg, nil)
    if err != nil {
        log.Fatalf("Error calling contract: %v", err)
    }
    log.Printf("Owner: %s", common.BytesToAddress(res).Hex())
}

答案 1 :(得分:1)

如果查看客户端库代码,您将看到JSON RPC响应对象已经被反汇编,并且在失败时返回错误,或者对实际结果进行了解析:https://github.com/ethereum/go-ethereum/blob/master/rpc/client.go#L277

然而,解析器已经解开了包含的“结果”字段。您的类型仍想进行其他拆包:

type response struct {
    Result string
}

删除外部结构,只需将字符串指针传递到client.Call的第一个参数即可。

答案 2 :(得分:0)

您的响应结构未显示响应的json具有的数据

尝试

type response struct {
    Jsonrpc string `json:"jsonrpc"`
    ID      int    `json:"id"`
    Result  string `json:"result"`
}

答案 3 :(得分:0)

json:无法将字符串解组为main.response错误类型的Go值。我在解组响应时遇到类似的类型错误。这是因为响应实际上是json字符串,我的意思是它的第一个字符为引号"。因此,为确保您也遇到相同的问题,请printf("%v",resp.Result),然后再在此处https://github.com/ethereum/go-ethereum/blob/1ff152f3a43e4adf030ac61eb5d8da345554fc5a/rpc/client.go#L278进行编组。