PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/daily/englishauction/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / daily / englishauction
Files
3 (README)(gnomod.toml)
Exported functions
5
Module
gno.land/r/moul/x/daily/englishauction/v0
gno
0.9

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • englishauction.gnogno
englishauction.gnogno
1// Package englishauction is an idiomatic gno.land port of the classic Solidity2// English (ascending-bid) auction. Anyone can Start an auction for a named item3// with a duration in blocks; bidders call Bid with a strictly increasing amount.4// The previous highest bid becomes refundable (claim it with Withdraw). After5// the auction's end height anyone may call End, awarding the item to the highest6// bidder. Auctions and pending refunds live in ordered avl trees so Render can7// iterate deterministically.8package englishauction910import (11	"strconv"1213	"chain"14	"chain/runtime"15	"chain/runtime/unsafe"1617	"gno.land/p/nt/avl/v0"18)1920// Auction is a single ascending-bid auction.21type Auction struct {22	ID            int6423	Seller        address24	Item          string25	EndHeight     int6426	HighestBid    uint6427	HighestBidder address28	Ended         bool29}3031var (32	auctions avl.Tree // key(id) -> *Auction33	pending  avl.Tree // "<id>:<addr>" -> uint64 refundable amount34	nextID   int64    = 135)3637// key formats an id into a zero-padded, lexicographically-sortable string.38func key(id int64) string {39	s := strconv.FormatInt(id, 10)40	for len(s) < 12 {41		s = "0" + s42	}43	return s44}4546// pendKey formats the refund key for a given auction id and bidder.47func pendKey(id int64, bidder address) string {48	return key(id) + ":" + bidder.String()49}5051// Start opens a new auction for `item` running for `durationBlocks` blocks from52// the current height. The caller becomes the seller. Returns the auction id.53func Start(cur realm, item string, durationBlocks int64) int64 {54	if item == "" {55		panic("englishauction: item must not be empty")56	}57	if durationBlocks <= 0 {58		panic("englishauction: duration must be > 0 blocks")59	}60	seller := unsafe.PreviousRealm().Address()61	id := nextID62	nextID++6364	a := &Auction{65		ID:        id,66		Seller:    seller,67		Item:      item,68		EndHeight: runtime.ChainHeight() + durationBlocks,69	}70	auctions.Set(key(id), a)7172	chain.Emit("Start",73		"id", strconv.FormatInt(id, 10),74		"seller", seller.String(),75		"item", item,76		"endHeight", strconv.FormatInt(a.EndHeight, 10),77	)78	return id79}8081// Bid places a bid of `amount` on auction `id`. It must strictly exceed the82// current highest bid. The displaced highest bid becomes refundable to its83// bidder via Withdraw.84func Bid(cur realm, id int64, amount uint64) {85	a := mustGet(id)86	if a.Ended || runtime.ChainHeight() >= a.EndHeight {87		panic("englishauction: auction has ended")88	}89	if amount <= a.HighestBid {90		panic("englishauction: bid must strictly exceed current highest")91	}92	bidder := unsafe.PreviousRealm().Address()93	if bidder == a.Seller {94		panic("englishauction: seller cannot bid")95	}9697	// The prior top bid becomes refundable (accumulate in case of repeats).98	if a.HighestBid > 0 {99		pk := pendKey(id, a.HighestBidder)100		pending.Set(pk, pendingOf(id, a.HighestBidder)+a.HighestBid)101	}102103	a.HighestBid = amount104	a.HighestBidder = bidder105106	chain.Emit("Bid",107		"id", strconv.FormatInt(id, 10),108		"bidder", bidder.String(),109		"amount", strconv.FormatUint(amount, 10),110	)111}112113// Withdraw refunds the caller's accumulated displaced bids for auction `id`.114// Returns the amount refunded (0 if nothing pending).115func Withdraw(cur realm, id int64) uint64 {116	mustGet(id) // ensure auction exists117	caller := unsafe.PreviousRealm().Address()118	amount := pendingOf(id, caller)119	if amount == 0 {120		return 0121	}122	pending.Remove(pendKey(id, caller))123	chain.Emit("Withdraw",124		"id", strconv.FormatInt(id, 10),125		"bidder", caller.String(),126		"amount", strconv.FormatUint(amount, 10),127	)128	return amount129}130131// End closes auction `id` once its end height is reached, awarding the item to132// the highest bidder (if any). Anyone may call it.133func End(cur realm, id int64) {134	a := mustGet(id)135	if a.Ended {136		panic("englishauction: auction already ended")137	}138	if runtime.ChainHeight() < a.EndHeight {139		panic("englishauction: auction not yet over")140	}141	a.Ended = true142143	chain.Emit("End",144		"id", strconv.FormatInt(id, 10),145		"winner", a.HighestBidder.String(),146		"amount", strconv.FormatUint(a.HighestBid, 10),147	)148}149150// --- read-only helpers (safe from tests and Render) ---151152// mustGet returns the auction for `id`, panicking if it does not exist.153func mustGet(id int64) *Auction {154	v := auctions.Get(key(id))155	if v == nil {156		panic("englishauction: no such auction")157	}158	return v.(*Auction)159}160161// pendingOf returns the refundable amount owed to `bidder` for auction `id`.162func pendingOf(id int64, bidder address) uint64 {163	v := pending.Get(pendKey(id, bidder))164	if v == nil {165		return 0166	}167	return v.(uint64)168}169170// blocksLeft returns how many blocks remain before `a` can be ended (0 if the171// end height has been reached).172func blocksLeft(a *Auction, height int64) int64 {173	if height >= a.EndHeight {174		return 0175	}176	return a.EndHeight - height177}178179// hasWinner reports whether the auction received at least one bid.180func hasWinner(a *Auction) bool {181	return a.HighestBid > 0182}183184// Render lists every auction with item, top bid + bidder, time left, and winner.185func Render(path string) string {186	out := "# English Auction\n\n"187	out += "Ascending-bid auctions. Start one, outbid others, and End it after "188	out += "its block deadline to award the item to the top bidder.\n\n"189190	if auctions.Size() == 0 {191		out += "_No auctions yet. Call `Start` to open one._\n"192		return out193	}194195	height := runtime.ChainHeight()196	out += "_Current block height: " + strconv.FormatInt(height, 10) + "_\n\n"197	out += "| ID | Item | Highest Bid | Bidder | Status | Winner |\n"198	out += "|---:|------|------------:|--------|--------|--------|\n"199200	auctions.Iterate("", "", func(_ string, v interface{}) bool {201		a := v.(*Auction)202203		bidStr := "—"204		bidderStr := "—"205		if hasWinner(a) {206			bidStr = strconv.FormatUint(a.HighestBid, 10)207			bidderStr = "`" + a.HighestBidder.String() + "`"208		}209210		status := ""211		winner := "—"212		switch {213		case a.Ended:214			status = "ended"215			if hasWinner(a) {216				winner = "`" + a.HighestBidder.String() + "`"217			} else {218				winner = "no bids"219			}220		case height >= a.EndHeight:221			status = "awaiting End"222		default:223			status = strconv.FormatInt(blocksLeft(a, height), 10) + " blocks left"224		}225226		out += "| " + strconv.FormatInt(a.ID, 10) + " | " + a.Item + " | " +227			bidStr + " | " + bidderStr + " | " + status + " | " + winner + " |\n"228		return false229	})230	return out231}232

Functions

  • Bid(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64, amount uint64)

  • End(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64)

  • Render(path string) string

  • Start(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, item string, durationBlocks int64) int64

  • Withdraw(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id int64) uint64

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.