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

answer.gno

3.01 Kb · 99 lines
 1package kourtv3
 2const answerWindow = 3 * epochBlocks
 3func PostAnswer(cur realm, courtSlug string, claimID uint64, verdict int) {
 4	if !cur.IsCurrent() {
 5		panic(errStaleRealm)
 6	}
 7	who := cur.Previous().Address()
 8	c := mustCourt(courtSlug)
 9	cs := mustClaim(c, claimID)
10	mustSide(verdict)
11	if cs.closed {
12		panic("kourtv3: this claim is closed")
13	}
14	if cs.frozenAt != 0 {
15		panic("kourtv3: this claim already has an answer")
16	}
17	now := heightNow()
18	if passed, known := pastDeadline(cs.openedAtTime, deadClaimSecs); (known && passed) ||
19		(!known && now >= cs.openedAt+deadClaimTimeout) {
20		panic("kourtv3: this claim is past the dead-claim timeout; it closes, it is not answered")
21	}
22	xbar, mature := cs.oi.Average(now, answerWindow)
23	if !mature {
24		panic("kourtv3: not enough stake history to answer yet")
25	}
26	if xbar < effMinAnswerX(c) {
27		panic("kourtv3: trailing stake is below the minimum to answer")
28	}
29	inPriority := false
30	if passed, known := pastDeadline(cs.openedAtTime,
31		blocksToSecs(c.params.stakeOpenDelayBlocks+answerWindow)+priorityWindowSecs); priorityGateActive(c) &&
32		((known && !passed) ||
33			(!known && now < cs.openedAt+c.params.stakeOpenDelayBlocks+answerWindow+priorityWindowBlocks)) {
34		if !mayAnswerInPriority(c, who) {
35			panic("kourtv3: the priority window is open — a qualified answerer may act first (wait ~24h)")
36		}
37		inPriority = true
38	}
39	touch(c)
40	advancePools(c, cs)
41	if life := lifeAvgStake(cs, now); life > xbar {
42		xbar = life
43	}
44	bond := xbar * answerBondBps / 10000
45	if c.params.answerBondCapCC > 0 && bond > c.params.answerBondCapCC {
46		bond = c.params.answerBondCapCC
47	}
48	convHi, convLo := cs.sideConv(verdict)
49	floor := bondFloorAt(xbar, convHi, convLo)
50	oppHi, oppLo := cs.sideConv(oppositeSide(verdict))
51	if opp := bondFloorAt(xbar, oppHi, oppLo); opp > floor {
52		floor = opp
53	}
54	if floor > bond {
55		bond = floor
56	}
57	if bond < 1 {
58		bond = 1
59	}
60	mustSpendable(c, who, bond)
61	c.coin.Transfer(who, c.escrow, bond)
62	cs.frozenAt = now
63	cs.rateAccAtFreeze = c.rateAccFP
64	cs.xBarFrozen = xbar
65	cs.tierRef = tierRefAt(c)
66	observeClaimSize(c, xbar)
67	cs.yesStakeAtFreeze, cs.noStakeAtFreeze = cs.yesStake, cs.noStake
68	cs.answer = int8(verdict)
69	cs.answerer = who
70	cs.answerBond = bond
71	cs.answerBond0 = bond
72	cs.answerHeight = now
73	cs.answeredAtTime = nowTime()
74	if inPriority {
75		holdPriority(c, who, claimID)
76	}
77	pendingExit(c, cs)
78	stripEnter(c, cs)
79	onClaimAnswered(c, cs)
80}
81func HasAnswer(courtSlug string, claimID uint64) bool {
82	return mustClaim(mustCourt(courtSlug), claimID).frozenAt != 0
83}
84func AnswerVerdict(courtSlug string, claimID uint64) int {
85	cs := mustClaim(mustCourt(courtSlug), claimID)
86	if cs.frozenAt == 0 {
87		panic("kourtv3: no answer yet")
88	}
89	return int(cs.answer)
90}
91func AnswerBond(courtSlug string, claimID uint64) int64 {
92	return mustClaim(mustCourt(courtSlug), claimID).answerBond
93}
94func Answerer(courtSlug string, claimID uint64) address {
95	return mustClaim(mustCourt(courtSlug), claimID).answerer
96}
97func XBarFrozen(courtSlug string, claimID uint64) int64 {
98	return mustClaim(mustCourt(courtSlug), claimID).xBarFrozen
99}