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.

/p/nym-moultest123/x/daily/pullpayment/v0

Directory · 4 Files
README.md Open

gno.land/p/nym-moultest123/x/daily/pullpayment/v0

Pull-payment escrow ledger — New, Credit, CreditMany, Withdraw, Forfeit, Balance, TotalOwed, TotalWithdrawn, Payees, Iterate, Consistent, MaxPayees.

1import "gno.land/p/nym-moultest123/x/daily/pullpayment/v0"
2
3l := pullpayment.New()
4l.CreditMany([]string{"alice", "bob"}, []int64{500, 300})
5l.TotalOwed()          // 800 — what the realm must keep in reserve
6
7amt, err := l.Withdraw("bob")   // 300; the balance is ALREADY zeroed
8// ...the caller transfers `amt` only now

The classic Solidity answer to reentrancy: never push value to an address, credit it and let the recipient withdraw. A push hands control to the recipient in the middle of your state transition, and a hostile recipient re-enters before you have finished updating.

This package is the bookkeeping half only — it moves no coins. The realm holding the funds transfers after calling Withdraw, which is exactly the ordering the pattern demands: checks, effects, then interactions. The balance is already deleted when control leaves, so a reentrant Withdraw returns ErrNothing and TotalWithdrawn is not double-counted. That property has its own test.

Other guarantees, each tested:

  • CreditMany is all-or-nothing. A batch with one bad entry applies none of itself — a ledger half-agreeing with the funds it guards is worse than a rejected call.
  • Overflow is refused, not wrapped, on both a single balance and the total.
  • Consistent() is exported: TotalOwed always equals the sum of the balances.

Payees comes back sorted, never in map order, so a Render built from it cannot differ between nodes.

Live demo: r/moul/x/daily/pullpaymentdemo · render it at /r/nym-moultest123/x/daily/pullpaymentdemo/v0.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.