Escrow vs push
Section titled “Escrow vs push”Boon.tip() has one sender action and two recipient outcomes.
Sender wallet │ approve(BoonContract, amount) if needed │ Boon.tip(handleHash, displayHandle, amount, note) ▼┌──────────────────────────────────────────────────────────┐│ Boon.sol on Base ││ ─ always emit Tip (intent event, indexed by subgraph) ││ ││ ┌── linkedWallet[handleHash] == 0x0 ? ││ │ │ yes → escrow[handleHash] += amount ││ │ │ (recipient claims later, no expiry) ││ │ │ ││ │ └ no → transfer USDC to linked wallet ││ │ → emit Pushed ││ └───────────────────────────────────────────────────── │└──────────────────────────────────────────────────────────┘ │ ▼Subgraph: Tip status = ESCROWED or PUSHEDIf the handle is not linked
Section titled “If the handle is not linked”- The sender transfers USDC into the Boon contract.
- The contract emits
Tip. - The amount is added to
escrow[handleHash]. - The recipient can later prove the handle and claim.
Escrow does not expire. The sender cannot recall it.
If the handle is linked
Section titled “If the handle is linked”- The sender transfers USDC into the Boon contract.
- The contract emits
Tip. - The contract transfers USDC to the linked wallet.
- The contract emits
Pushed.
Future boons to the same handle push automatically after the first successful link.
Claiming escrow
Section titled “Claiming escrow”After a handle is linked, anyone can call claim(handleHash). The contract sends escrow only to linkedWallet[handleHash], never to the caller unless the caller is also the linked wallet.
Value-at-risk hardening
Section titled “Value-at-risk hardening”A normal link() can bind a handle with no existing escrow. A pre-funded handle uses linkEscrowed() and requires both the trusted OAuth signer and escrow guardian to sign the same Link digest. That reduces the blast radius of a single signer leak for already-escrowed value.