與GETH模擬後端的智能合約交互

我正在發布我的「hacky」golang測試環境,該環境深入鏈接到go-ethereum代碼庫。

這是該系列的下一個……

現在您已經運行了模擬的以太坊網路,現在是時候看到EVM在運行了。

GETH附帶了一個非常有用的工具,可以幫助您將GO代碼與可靠的智能合約集成。

介紹ABIGEN

ABIGEN圍繞您的智能合約創建一個盤點器,以幫助您進行大多數您可能想要執行的交互。

我通常將合約存儲在具有適當名稱的子文件夾中。

在這種情況下,我正在為Devcon 5拍賣合約進行測試。我將它放在contracts文件夾中。

您可以在此處找到實際的拍賣合約

https://etherscan.io/address/0x096bE08D7d1CaeEA6583eab6b75a0f5EaaB012a5#code

如果我們將該源代碼放入auction.sol合約文件夾中,您將創建盤點器:

abigen --sol contracts/auction.sol --pkg contracts --out contracts/auction.go

合約的名稱是auction這樣的,ABIGEN將創建一個名為的函數DeployAuction

您會注意到構造函數需要一些日期參數,金額和錢包地址,我們首先創建一個輔助函數。

func chkerr(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

// I like British dates !
func getTime(dateStr string) *big.Int {
    t, err := time.Parse("02/01/06", dateStr)
    chkerr(err)
    return big.NewInt(t.Unix())
}

現在創建構造函數變數

    startBids := getTime("13/09/19")
    endBids := getTime("15/09/19")
    startReveal := endBids
    endReveal := getTime("17/09/19")
    minimumBid, _ := etherUtils.StrToEther("4.7")
    wallet, _ := memorykeys.GetAddress("wallet")

現在部署合約……

    bankTx, _ := memorykeys.GetTransactor("banker")
    auctionAddress, tx, auctionContract, err := contracts.DeployAuction(bankTx, client, startBids, endBids, startReveal, endReveal minimumBid, *wallet)
    chkerr(err)
    fmt.Println(auctionAddress.Hex(), tx.Hash().Hex())

我們需要一個綁定的transactor(參見memoryke​​ys post)然後我們發送事務來部署返回的合約

  1. 合約的地址
  2. 允許我們與它進行交易的綁定對象(一旦部署)
  3. 事務對象
  4. 一個錯誤對象(像往常一樣)

我們現在可以導致該交易被挖礦

    client.Commit()

然後我們可以在合約中調用一個方法,讓我們檢查最低出價

    min, err := auctionContract.MinimumBid(nil)
    chkerr(err)
    fmt.Println("minumum bid is ", etherUtils.EtherToStr(min))

運行testAuction.go我們將獲得隨機分配的地址,但最低出價將被清楚地看作是4.7

$go run testAuction.go
0x8095E4E397c8BEDffE7d2c8E3EaA30F646aab6dC 0x24fa2c113beab3eecf2129ef868e9121c3a7d8f7e084c6c66fbd10cb67b680a5
4.700000000000000000

獎金 – 瓶中的時間

Devcon5拍賣合約是一項時間依賴合約。分為三個階段:

  1. 招標期
  2. 揭示時期
  3. 提款期

如果我們想測試這樣的合約,我們需要能夠加快區塊鏈時鐘到達特定時間。

獲得模擬區塊鏈的時間

func currentTime() uint64 {
    client, err := getClient()
    chkerr(err)
    block := client.Blockchain().CurrentBlock()
    return block.Time()
}

及時跳躍

我對go-ethereum代碼庫的小貢獻是AdjustTime模擬後端的功能。

func jumpTo(newTime *big.Int) {
    client, err := getClient()
    chkerr(err)
    now := client.Blockchain().CurrentBlock().Time()
    target := newTime.Uint64()
    if now >= target {
        return
    }
    err = client.AdjustTime(time.Duration(target-now) * time.Second)
    chkerr(err)
    client.Commit()
}

我們還可以創建一個功能來報告投標是否公開

func isBiddingOpen(auction *contracts.Auction) {
    biddingOpen, err := auction.InBidding(nil)
    chkerr(err)
    state := "IS NOT"
    if biddingOpen {
        state = "IS"
    }
    fmt.Println("Bidding", state, "open")
}

因此,這允許我們跳轉到測試的開始。

    fmt.Println("time:",currentTime())
    isBiddingOpen(auctionContract)
    jumpTo(startBids)
    fmt.Println("time:",currentTime())
    isBiddingOpen(auctionContract)
$go run testAuction.go
0x06cfB9BD9a3093603EFf47BC0679A729AF6a884c 0x0bf7dd3223934f955981816fda317e7fa6b669252c5a5695c71d3d82451b604f
minumum bid is  4.700000000000000000
time : 10
Bidding IS NOT open
time : 1568332810
Bidding IS open

完整的代碼

package main

import (
    "fmt"
    "log"
    "math/big"
    "os"
    "time"

    "./contracts"

    "github.com/DaveAppleton/etherUtils"
    "github.com/DaveAppleton/memorykeys"
    "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
    "github.com/ethereum/go-ethereum/core"
)

var baseClient *backends.SimulatedBackend

func getClient() (client *backends.SimulatedBackend, err error) {
    if baseClient != nil {
        return baseClient, nil
    }
    funds, _ := etherUtils.StrToEther("10000.0")
    bankerAddress, err := memorykeys.GetAddress("banker")
    if err != nil {
        return nil, err
    }
    baseClient = backends.NewSimulatedBackend(core.GenesisAlloc{
        *bankerAddress: {Balance: funds},
    }, 8000000)
    return baseClient, nil
}

func chkerr(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

func getTime(dateStr string) *big.Int {
    t, err := time.Parse("02/01/06", dateStr)
    chkerr(err)
    return big.NewInt(t.Unix())
}

func currentTime() uint64 {
    client, err := getClient()
    chkerr(err)
    block := client.Blockchain().CurrentBlock()
    return block.Time()
}

func jumpTo(newTime *big.Int) {
    client, err := getClient()
    chkerr(err)
    now := client.Blockchain().CurrentBlock().Time()
    target := newTime.Uint64()
    if now >= target {
        return
    }
    err = client.AdjustTime(time.Duration(target-now) * time.Second)
    chkerr(err)
    client.Commit()
}

func isBiddingOpen(auction *contracts.Auction) {
    biddingOpen, err := auction.InBidding(nil)
    chkerr(err)
    state := "IS NOT"
    if biddingOpen {
        state = "IS"
    }
    fmt.Println("Bidding", state, "open")
}

func main() {
    client, err := getClient()
    if err != nil {
        log.Fatal(err)
    }
    startBids := getTime("13/09/19")
    endBids := getTime("15/09/19")
    startReveal := endBids
    endReveal := getTime("17/09/19")
    minimumBid, _ := etherUtils.StrToEther("4.7")
    wallet, _ := memorykeys.GetAddress("wallet")
    bankTx, _ := memorykeys.GetTransactor("banker")
    auctionAddress, tx, auctionContract, err := contracts.DeployAuction(bankTx, client, startBids, endBids, startReveal, endReveal, minimumBid, *wallet)
    chkerr(err)
    fmt.Println(auctionAddress.Hex(), tx.Hash().Hex())
    client.Commit()
    min, err := auctionContract.MinimumBid(nil)
    chkerr(err)
    fmt.Println("minumum bid is ", etherUtils.EtherToStr(min))
    fmt.Println("time :", currentTime())
    isBiddingOpen(auctionContract)
    jumpTo(startBids)
    fmt.Println("time :", currentTime())
    isBiddingOpen(auctionContract)
}
原文 Kauri
提示:投資有風險,入市需謹慎,本資訊不作為投資理財建議。請理性投資,切實提高風險防範意識;如有發現的違法犯罪線索,可積極向有關部門舉報反映。
你可能還喜歡