Denom
untyped stringValue
"ugnot"
Path
untyped stringValue
"gno.land/r/moul/faucet/v0"
Link
untyped stringValue
"/r/moul/faucet/v0"
Owner
.uverse.addressOwner funds the faucet, approves by default, and is the only account that can change who else approves or take the float back. Hardcoded rather than captured from the deployer: inside a plain \`func Test(t \*testing.T)\` the gno test runner reports OriginCaller() as the EMPTY address, so an owner seeded from it is empty in every test and something else on chain. That divergence is where an authorization bug hides, so the address is written down.
Value
<gnolang.StringValue>
StatusPending
untyped stringThe three states a request can be in. A request is decided exactly once.
Value
"pending"
StatusSent
untyped stringThe three states a request can be in. A request is decided exactly once.
Value
"sent"
StatusDenied
untyped stringThe three states a request can be in. A request is decided exactly once.
Value
"denied"
DefaultMaxPerRequest
untyped bigintValue
(200000000 <untyped> bigint)
MaxReasonLen
untyped bigintValue
(280 <untyped> bigint)
idWidth
untyped bigintValue
(12 <untyped> bigint)
request
typerequest is one ask. It is unexported because avl stores \`any\` and the readable surface of this realm is its views and its page, not a struct another realm would have to depend on.
Value
v0.request
requests
v0.Tree// padded id -> \*request
- OID
- 0b3cd8…35a5:50
requests details
paid
v0.Tree// recipient address -> int64 ugnot received in total
- OID
- 0b3cd8…35a5:51
paid details
approvers
v0.Tree// approver address -> bool
- OID
- 0b3cd8…35a5:52
approvers details
nextID
int64Value
3
maxPerRequest
int64Value
200000000
totalSent
int64Value
110000000
sentCount
int64Value
2
deniedCount
int64Value
0
pendingN
int64Value
0
init.20
func()- OID
- 0b3cd8…35a5:15
init.20 details
reset
func()reset installs an empty faucet. Also called by the tests: realm globals persist for a whole test binary and examples run after every Test, so a pinned Render has to start from a known state.
- OID
- 0b3cd8…35a5:17
reset details
Address
func() .uverse.address- OID
- 0b3cd8…35a5:18
Address details
Balance
func() int64Balance is what the faucet can actually pay out right now.
- OID
- 0b3cd8…35a5:19
Balance details
NextID
func() int64NextID is the id the next [Request](#Request) will be given. Read it to build the [Approve](#Approve) half of a two-message transaction, and pass the recipient and amount to Approve so that a request landing in between fails the transaction instead of being paid by it.
- OID
- 0b3cd8…35a5:20
NextID details
MaxPerRequest
func() int64MaxPerRequest is the current cap on a single payout, in ugnot.
- OID
- 0b3cd8…35a5:21
MaxPerRequest details
TotalSent
func() int64TotalSent, SentCount, DeniedCount and Pending are the running tallies.
- OID
- 0b3cd8…35a5:22
TotalSent details
SentCount
func() int64- OID
- 0b3cd8…35a5:23
SentCount details
DeniedCount
func() int64- OID
- 0b3cd8…35a5:24
DeniedCount details
Pending
func() int64- OID
- 0b3cd8…35a5:25
Pending details
Requests
func() intRequests is how many requests have ever been filed.
- OID
- 0b3cd8…35a5:26
Requests details
IsApprover
func(addr string) boolIsApprover reports whether addr may approve or deny.
- OID
- 0b3cd8…35a5:27
IsApprover details
ReceivedBy
func(addr string) int64ReceivedBy is everything this faucet has ever paid to addr.
- OID
- 0b3cd8…35a5:28
ReceivedBy details
Status
func(id int64) stringStatus is the state of request id: "pending", "sent", "denied", or "" when no such request exists.
- OID
- 0b3cd8…35a5:29
Status details
Fund
func()Fund credits the ugnot sent with the call to the float. Coins sent straight to \[Address] land there too; they just do not emit an event.
- OID
- 0b3cd8…35a5:30
Fund details
Request
func(to string, amount int64, reason string) int64Request files an ask for amount ugnot to be paid to \`to\`, and returns its id. Anyone may file, for anyone, which is the point: the account that needs the coins is the one that cannot pay to ask for them. Filing costs the filer gas and nothing else, and moves no money.
- OID
- 0b3cd8…35a5:31
Request details
Approve
func(id int64, wantTo string, wantAmount int64)Approve pays request id out of the float. Approvers only. wantTo and wantAmount are not redundant: they are what makes it safe to put Approve in the same transaction as the Request it settles. The id has to be guessed from [NextID](#NextID) before either message is signed, and this call refuses when the request sitting at that id is not the one the caller described.
- OID
- 0b3cd8…35a5:32
Approve details
Deny
func(id int64, why string)Deny closes a request unpaid, with a reason that goes on the page. The reason is the whole value of denying in public rather than ignoring it.
- OID
- 0b3cd8…35a5:33
Deny details
AddApprover
func(addr string)AddApprover lets addr approve and deny. Owner only.
- OID
- 0b3cd8…35a5:34
AddApprover details
RemoveApprover
func(addr string)RemoveApprover revokes addr. Owner only, and the Owner cannot be removed: a faucet with no approver is a faucet with a locked float.
- OID
- 0b3cd8…35a5:35
RemoveApprover details
SetMaxPerRequest
func(amount int64)SetMaxPerRequest changes the per-request cap, in ugnot. Owner only.
- OID
- 0b3cd8…35a5:36
SetMaxPerRequest details
Withdraw
func(amount int64)Withdraw returns amount ugnot of the float to the Owner. Owner only. This is what makes funding the faucet reversible, and it is deliberately not payable to an arbitrary address: an approver who wanted to move money somewhere has to file a request for it like everyone else.
- OID
- 0b3cd8…35a5:37
Withdraw details
mustOwn
func(caller .uverse.address)- OID
- 0b3cd8…35a5:38
mustOwn details
mustApprove
func(caller .uverse.address)- OID
- 0b3cd8…35a5:39
mustApprove details
find
func(id int64) *v0.request- OID
- 0b3cd8…35a5:40
find details
key
func(id int64) stringkey pads an id to idWidth digits so the avl tree iterates in filing order.
- OID
- 0b3cd8…35a5:41
key details
Render
func(path string) stringRender shows the float, the open asks and everything already decided. Two paths: "" is the whole board, "req/\<id>" is one request. Every string on this page that a caller typed goes through sanitize before it is concatenated. A reason is arbitrary text from an arbitrary account and Render output is markdown that gnoweb parses, so an unescaped one can plant a link, an image beacon or gnoweb chrome on a page the realm is signing for. This realm's path is permanent, so that bug could only ever be fixed at a new path.
- OID
- 0b3cd8…35a5:42
Render details
renderBoard
func() string- OID
- 0b3cd8…35a5:44
renderBoard details
table
func(want string) stringtable lists requests in filing order, keeping only those in \`want\`, or everything already decided when want is empty.
- OID
- 0b3cd8…35a5:45
table details
renderOne
func(id int64) string- OID
- 0b3cd8…35a5:46
renderOne details
reqPath
func(path string) (int64, bool)reqPath parses "req/\<id>".
- OID
- 0b3cd8…35a5:47
reqPath details
excerpt
func(s string, width int) stringexcerpt cuts to width RUNES, never bytes: slicing a multi-byte character in half puts invalid UTF-8 on the page, and one emoji in a reason is enough. It cuts before escaping, because escaping inserts backslashes and cutting an already-escaped string can strand a lone one that escapes the chrome after it.
- OID
- 0b3cd8…35a5:48
excerpt details
gnot
func(ugnot int64) stringgnot renders ugnot as GNOT with the trailing zeros of the fraction trimmed, so 100000000 reads as 100 and 1500000 as 1.5.
- OID
- 0b3cd8…35a5:49
gnot details
intro
untyped stringValue
"Somebody you trust has no GNOT and cannot use the public faucet. File a\nrequest on their behalf, an approver releases it, and both halves stay on\nthis page with a reason attached. The faucet only ever spends what has been\nsent to its own address."
howto
untyped stringValue
"## How\n\n`Request(to, amount, reason)` is open to anyone and moves no money.\n`Approve(id, to, amount)` pays it, and only an approver can call it.\n\nSend both in **one transaction**: a tm2 transaction stops at the first\nmessage that fails and writes none of t"...