Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

organizer.gno

3.91 Kb · 127 lines
  1package bolo
  2
  3import (
  4	"chain"
  5	"chain/banker"
  6	"chain/runtime"
  7	"math"
  8)
  9
 10// Who hid a campaign's photo: ImageHidden's by (API §6).
 11const (
 12	hiderOrganizer = "organizer"
 13	hiderModerator = "moderator"
 14)
 15
 16// PostBond adds what you send to campaign id's bond: a stake its organizer may post,
 17// lost if Bolo's moderator delists the campaign for fraud. It is not a guarantee. The
 18// organizer only, while the campaign is open.
 19//
 20// It adds the envelope to the campaign's bond (API §3.1): its organizer only, by a
 21// direct transaction, while the campaign is open, its bond unslashed and Bolo not
 22// paused. The bond only grows, and the coins go on to the bond address: the
 23// realm keeps nothing (INV-3).
 24func PostBond(cur realm, id string) {
 25	assertCurrent(cur)
 26	if !cur.Previous().IsUserCall() {
 27		panic(ErrNotUserCall)
 28	}
 29	runtime.AssertOriginCall()
 30	c := campaignOf(id)
 31	recordDeadline(cur, c)
 32	if cur.Previous().Address() != c.organizer {
 33		panic(ErrNotOrganizer)
 34	}
 35	amount := envelopeUgnot()
 36	checkBond(c, amount)
 37	c.state.bond += amount
 38	banker.NewBanker(banker.BankerTypeRealmSend, cur).SendCoins(realmAddr(), bondAddr(c.id), chain.NewCoins(chain.NewCoin("ugnot", amount)))
 39	chain.Emit(evBondPosted, "id", idString(c.id), "amount", itoa(amount), "bond", itoa(c.state.bond))
 40}
 41
 42// checkBond refuses amount as more bond for c (API §3.1), in this order: nothing
 43// sent, a campaign that isn't open, a slashed bond, a paused Bolo, and a bond that
 44// would pass int64.
 45func checkBond(c *campaign, amount int64) {
 46	if amount <= 0 {
 47		panic(ErrBadAmount)
 48	}
 49	assertOpen(c)
 50	if c.state.bondSlashed {
 51		panic(ErrBondSlashed)
 52	}
 53	if paused {
 54		panic(ErrPaused)
 55	}
 56	if amount > math.MaxInt64-c.state.bond {
 57		panic(ErrBadAmount)
 58	}
 59}
 60
 61// assertOpen refuses a campaign that isn't open, by its stored status:
 62// ErrCampaignSettled once settled, ErrCampaignClosed otherwise. A passed deadline
 63// is recorded before (API §3.1).
 64func assertOpen(c *campaign) {
 65	switch c.state.status {
 66	case statusOpen:
 67	case statusSettled:
 68		panic(ErrCampaignSettled)
 69	default:
 70		panic(ErrCampaignClosed)
 71	}
 72}
 73
 74// PostUpdate posts an update on campaign id, shown under its story, and returns the
 75// update's number: its organizer only. body may hold links, never an image.
 76//
 77// It appends an update to the campaign (API §3.1): its organizer only, by a direct
 78// transaction, in every status and while paused. Updates are append-only, and each
 79// resets the dormancy clock.
 80func PostUpdate(cur realm, id, body string) string {
 81	assertCurrent(cur)
 82	if !cur.Previous().IsUserCall() {
 83		panic(ErrNotUserCall)
 84	}
 85	runtime.AssertOriginCall()
 86	c := campaignOf(id)
 87	recordDeadline(cur, c)
 88	if cur.Previous().Address() != c.organizer {
 89		panic(ErrNotOrganizer)
 90	}
 91	body = checkStory(body, updateMin, updateMax, ErrUpdate)
 92	s := c.state
 93	seq := s.updateSeq.Next()
 94	c.updates.Set(seq.Binary(), &update{seq: uint64(seq), at: now(), body: body})
 95	s.updateCount++
 96	s.lastUpdateAt = now()
 97	chain.Emit(evUpdatePosted, "id", idString(c.id), "seq", idString(seq))
 98	return idString(seq)
 99}
100
101// HideImage hides campaign id's photo, for good: its organizer can, and so can Bolo's
102// moderator.
103//
104// Its organizer may, by a direct transaction, and so may the moderator, with the
105// master key — a DAO realm, once one holds the role, through C11's realm branch (API
106// §3.1, §3.5). The CID stays: it is a fingerprint, and never replaced. Hiding a
107// hidden photo, or a campaign with none, changes nothing.
108func HideImage(cur realm, id string) {
109	assertCurrent(cur)
110	if cur.Previous().IsUserCall() {
111		runtime.AssertOriginCall()
112	} else {
113		assertCodeCaller(cur)
114	}
115	c := campaignOf(id)
116	recordDeadline(cur, c)
117	by := hiderOrganizer
118	if cur.Previous().Address() != c.organizer { // an organizer is a user: CreateCampaign admits no other
119		assertSigner(cur, admin)
120		by = hiderModerator
121	}
122	if c.text.imageCID == "" || c.state.imageHidden {
123		return
124	}
125	c.state.imageHidden = true
126	chain.Emit(evImageHidden, "id", idString(c.id), "by", by)
127}