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.

operator_faucet.gno

4.14 Kb · 172 lines
  1package admin
  2
  3import (
  4	"chain"
  5	"chain/banker"
  6
  7	"gno.land/p/akkadia/beta/accesscontrol"
  8)
  9
 10const (
 11	SetFaucetTargetAmountEvent = "SetFaucetTargetAmount"
 12	RequestFaucetEvent         = "RequestFaucet"
 13	RequestFaucetsEvent        = "RequestFaucets"
 14	WithdrawEvent              = "Withdraw"
 15)
 16
 17var (
 18	faucetTargetAmount int64
 19)
 20
 21func SetFaucetTargetAmount(cur realm, amount int64) {
 22	accesscontrol.AssertIsAdmin(0, cur, IsAdmin)
 23	assertPositiveFaucetTarget(amount)
 24
 25	oldAmount := faucetTargetAmount
 26	faucetTargetAmount = amount
 27
 28	chain.Emit(
 29		SetFaucetTargetAmountEvent,
 30		"oldAmount", int64ToString(oldAmount),
 31		"newAmount", int64ToString(amount),
 32	)
 33}
 34
 35func GetFaucetTargetAmount() int64 {
 36	return faucetTargetAmount
 37}
 38
 39func RequestFaucet(cur realm) int64 {
 40	caller := mustGetFaucetCaller(0, cur)
 41	assertPositiveFaucetTarget(faucetTargetAmount)
 42
 43	return sendFaucetDeficit(cur, caller, true)
 44}
 45
 46func RequestFaucetFor(cur realm, operator address) int64 {
 47	accesscontrol.AssertIsAdmin(0, cur, IsAdmin)
 48	assertPositiveFaucetTarget(faucetTargetAmount)
 49	assertFaucetOperator(operator)
 50
 51	return sendFaucetDeficit(cur, operator, true)
 52}
 53
 54func RequestFaucets(cur realm) int64 {
 55	accesscontrol.AssertIsAdmin(0, cur, IsAdmin)
 56	assertPositiveFaucetTarget(faucetTargetAmount)
 57
 58	bnk := banker.NewBanker(banker.BankerTypeRealmSend, cur)
 59	operators := GetOperators()
 60	deficitOperators := []address{}
 61	deficits := []int64{}
 62	totalAmount := int64(0)
 63
 64	for _, operator := range operators {
 65		deficit := getFaucetDeficit(bnk, operator)
 66		if deficit <= 0 {
 67			continue
 68		}
 69
 70		deficitOperators = append(deficitOperators, operator)
 71		deficits = append(deficits, deficit)
 72		totalAmount += deficit
 73	}
 74
 75	if totalAmount == 0 {
 76		return 0
 77	}
 78
 79	assertAdminRealmBalance(bnk, cur.Address(), totalAmount)
 80	for i, operator := range deficitOperators {
 81		sendAdminRealmUgnot(bnk, cur.Address(), operator, deficits[i])
 82		emitRequestFaucet(operator, deficits[i])
 83	}
 84
 85	chain.Emit(
 86		RequestFaucetsEvent,
 87		"amount", int64ToString(totalAmount),
 88		"targetAmount", int64ToString(faucetTargetAmount),
 89	)
 90
 91	return totalAmount
 92}
 93
 94func Withdraw(cur realm, recipient address, amount int64) int64 {
 95	accesscontrol.AssertIsAdmin(0, cur, IsAdmin)
 96	assertValidAddress(recipient)
 97	assertPositiveUgnotAmount(amount)
 98
 99	bnk := banker.NewBanker(banker.BankerTypeRealmSend, cur)
100	realmAddr := cur.Address()
101	assertAdminRealmBalance(bnk, realmAddr, amount)
102	sendAdminRealmUgnot(bnk, realmAddr, recipient, amount)
103
104	chain.Emit(
105		WithdrawEvent,
106		"recipient", recipient.String(),
107		"amount", int64ToString(amount),
108	)
109
110	return amount
111}
112
113func sendFaucetDeficit(cur realm, operator address, panicIfFunded bool) int64 {
114	bnk := banker.NewBanker(banker.BankerTypeRealmSend, cur)
115	amount := getFaucetDeficit(bnk, operator)
116	if amount <= 0 {
117		if panicIfFunded {
118			panic("operator balance is not below faucet target")
119		}
120		return 0
121	}
122
123	realmAddr := cur.Address()
124	assertAdminRealmBalance(bnk, realmAddr, amount)
125	sendAdminRealmUgnot(bnk, realmAddr, operator, amount)
126	emitRequestFaucet(operator, amount)
127
128	return amount
129}
130
131func getFaucetDeficit(bnk banker.Banker, operator address) int64 {
132	operatorBalance := bnk.GetCoins(operator).AmountOf("ugnot")
133	if operatorBalance >= faucetTargetAmount {
134		return 0
135	}
136
137	return faucetTargetAmount - operatorBalance
138}
139
140func assertAdminRealmBalance(bnk banker.Banker, realmAddr address, amount int64) {
141	realmBalance := bnk.GetCoins(realmAddr).AmountOf("ugnot")
142	if realmBalance < amount {
143		panic("admin realm balance is insufficient")
144	}
145}
146
147func sendAdminRealmUgnot(bnk banker.Banker, realmAddr address, recipient address, amount int64) {
148	coins := chain.Coins{chain.Coin{"ugnot", amount}}
149	bnk.SendCoins(realmAddr, recipient, coins)
150}
151
152func emitRequestFaucet(operator address, amount int64) {
153	chain.Emit(
154		RequestFaucetEvent,
155		"operator", operator.String(),
156		"amount", int64ToString(amount),
157		"targetAmount", int64ToString(faucetTargetAmount),
158	)
159}
160
161func mustGetFaucetCaller(_ int, rlm realm) address {
162	caller := accesscontrol.MustGetUserCaller(0, rlm)
163	assertFaucetOperator(caller)
164	return caller
165}
166
167func assertFaucetOperator(operator address) {
168	assertValidAddress(operator)
169	if !IsOperator(operator) {
170		panic("operator access required")
171	}
172}