Realm
v0
gno.land/r/moul/x/daily/pullpaymentdemo/v0
Render
Pull Payment
Credit and let recipients withdraw, demoing the p/moul/x/daily/pullpayment library.
Why not just send?
Pushing value hands control to the recipient in the middle of your state transition, and a hostile recipient re-enters before you have finished updating. Pulling inverts it: you record a debt, and the recipient's own withdrawal is the only state being touched.
A split, credited
| payee | owed |
|---|---|
alice | 500 |
bob | 300 |
carol | 200 |
The holding realm must keep 1000 in reserve — that is what TotalOwed is for.
Bob claims
Withdraw("bob") → 300, and the ledger is updated before the caller transfers anything:
| payee | owed |
|---|---|
alice | 500 |
carol | 200 |
Reserve is now 700.
The reentrancy attempt
Bob's handler calls straight back in, before the transfer completes:
- second
Withdraw("bob")→0, error:pullpayment: nothing to withdraw
Nothing left to take. The balance was deleted before control left the function — checks, effects, then interactions. Lifetime withdrawn is still 300, not double.
Credits accumulate
Credit("alice", 100) on top of her existing balance:
| payee | owed |
|---|---|
alice | 600 |
carol | 200 |
One withdrawal collects the lot — no dust left behind.
Batch credits are all-or-nothing
A split that is partly invalid applies none of itself; a ledger half-agreeing with the funds it guards is worse than a rejected call:
CreditMany([dave, eve], [10, -1])→pullpayment: amount must be positive- total owed before:
800, after:800— unchanged, anddavewas not credited
Transactions
No indexed transactions for this realm yet.
Calls, deploys, and child packages in indexed history.
Call function
Calls stay disabled until vm/qfuncs lists this package. Delve only submits functions the chain publishes for gno.land/r/moul/x/daily/pullpaymentdemo/v0.