doufuxi7093 2018-11-10 09:47
浏览 355
已采纳

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

Update

Since I'm not able to achieve this using the approach in this question, I created my own library to do the same thing (link). It doesn't rely on go-ethereum package but use the normal net/http package to do JSON RPC request.

I still love to know what I did wrong in my approach below.


Definitions:

  • owner = public variable in contract with address type
  • contract = smart-contract that has owner

This is the curl request to get the owner of a contract. I managed to get the owner. (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"}

But when I try to replicate it in Golang (code below), I got json: cannot unmarshal string into Go value of type main.response error. (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
", resp)
}

What did I miss here?

Expected result:

Address in string format. E.g. 0x3ab17372b25154400738C04B04f755321bB5a94b

P/S — I'm aware of abigen and I know it's better and easier to do this using abigen. But I'm trying to solve this specific issue without using abigen method.

  • 写回答

4条回答 默认 最新

  • dtz8044 2018-11-12 11:06
    关注

    You can solve the problem best using the 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())
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 如何构建全国统一的物流管理平台?
  • ¥100 ijkplayer使用AndroidStudio/CMake编译,如何支持 rtsp 直播流?
  • ¥20 和学习数据的传参方式,选择正确的传参方式有关
  • ¥15 这是网络安全里面的poem code
  • ¥15 用js遍历数据并对非空元素添加css样式
  • ¥15 使用autodl云训练,希望有直接运行的代码(关键词-数据集)
  • ¥50 python写segy数据出错
  • ¥20 关于线性结构的问题:希望能从头到尾完整地帮我改一下,困扰我很久了
  • ¥30 3D多模态医疗数据集-视觉问答
  • ¥20 设计一个二极管稳压值检测电路