Why the memo is the missing piece
A plain ERC-20Transfer tells you who paid whom, how much. It does not tell you what for. That single missing field is why onchain payments have historically needed a separate, off-chain mapping to be reconcilable at all.
TIP-20 adds it at the protocol level. Every payment can carry a 32-byte memo:
How it works
- Stream TIP-20 logs from Tempo with Turbo.
- Decode
TransferWithMemoon the fly using the token’s ABI. - Write each settlement - including the memo - into a
onchain_settlementstable co-located with your invoices. - Match settlements to invoices on the memo. Anything unmatched or short-paid surfaces as an exception the instant it settles.
Prerequisites
- The Turbo CLI extension installed and logged in to your project.
- A Postgres database and a Goldsky secret with its connection string.
- The contract address of the TIP-20 token you settle in, and its ABI. Confirm the exact Tempo dataset name in the Datasource explorer or with
goldsky dataset list.
Step 1: Stream and decode settlements
TIP-20 events are ordinary Solidity logs, so they land in theraw_logs dataset and can be decoded inside the pipeline. This mirrors the decode custom contract events pattern.
reconciliation-pipeline.yaml
Step 2: Reconcile against your ledger
Youronchain_settlements table now fills in real time, next to your existing invoices table. Because you control the memo, matching is a single join. Encode your invoice reference into the 32-byte memo when you create the payment (for example a zero-padded ID or a hash), and store the same encoding on the invoice.
unpaid past its due date, short_paid, or arrives with a memo that matches no invoice (an unexpected payment) is a reconciliation break - surfaced the moment it settles, not the next morning.
Step 3: Make exceptions live
Two options turn the query above into an always-on control.- Live exception totals (Postgres aggregate)
- Instant break alerts (webhook)
Use the PostgreSQL aggregate sink to maintain a running, real-time rollup - for example a running total settled per token - without a scheduled job.
Step 4: Trust your reads
Reconciliation is only as reliable as the data feeding it. Point the indexers and verification jobs behind this workflow at Edge RPC:- Cross-validation and block-range enforcement mean you never reconcile against a missing log or a gap in
eth_getLogs. - Automatic failover keeps the ledger current through provider outages.
Optional: auto-resolve breaks with Compose
For breaks that can be handled programmatically - retrying a failed payout, issuing a refund for an overpayment, or opening a ticket - trigger a Compose task from the exception. Compose gives you durable execution (the action completes even through failures) and a full trace of every step, so each automated resolution is auditable. See task triggers to fire a task from a webhook or onchain event.Business outcomes
- Reconciliation moves from overnight to real time. Breaks surface in seconds, not the next business day.
- Fewer manual matches. A deterministic memo join replaces amount-and-timestamp guesswork, shrinking the exception queue.
- Faster cash application. Payments apply to invoices as they settle, tightening working-capital cycles.
- A clean audit trail. Every settlement, its memo, and its match status live in your own database.
Resources
- Decode custom contract events with Turbo
- PostgreSQL aggregate sink
- Stablecoin transfers guide
- Tempo chain reference