In a peer-to-peer OTC trade on Kaspa Escrow, one side is straightforward: the buyer sends KAS into an on-chain covenant where the rules are enforced by code. But what about the other leg? If a seller agrees to send USDT on Tron, or BTC, or TON in exchange — how does the buyer know the counterparty payment actually happened?
Until recently, the answer was: check the explorer yourself, trust the chat messages, and hope for the best. That gap — between the cryptographically-enforced KAS side and the "just trust me" counterparty side — is what the cross-chain verification pipeline was built to close.
An advisory-only, server-side check that watches the counterparty blockchain (Tron, Ethereum, Bitcoin, etc.) and reports whether a declared payment transaction matches the deal's agreed terms — method, amount, and recipient address. It does not touch the Kaspa escrow contract.
The problem: one contract, two chains
Kaspa's escrow.sil covenant has ten spending paths, all of which enforce that funds go to the buyer, the seller, or the service fee address — and nowhere else. This gives strong guarantees on the KAS side of any deal. In a simple goods-for-KAS trade, that's enough: buyer funds the escrow, seller ships, buyer releases.
But OTC trades are different. Both sides move value: the buyer sends KAS into escrow, and the seller sends some other cryptocurrency directly on its native chain. The contract cannot see what happens on Tron or Ethereum — Kaspa's VM doesn't have cross-chain introspection. So the counterparty leg has always lived in a gray zone: declared in chat, verified by eyeballs.
This matters because disputes are heavy machinery. If a seller claims they sent USDT but didn't, the buyer has to open a dispute, reveal the chat key, and wait for AI forensics and possibly a human arbiter. The process works — our dispute and arbitration flow is designed for it — but it's expensive overhead for what might be a simple factual question: *did the transaction land?*
How verification works, step by step
The verification pipeline runs as a module inside the shared Kaspa Forge backend — the same process that handles Kaspa Safe, Escrow, Deposit, and Marketplace. Here's the flow:
1. Deal creation locks the terms
When an OTC deal is created or joined, the initiating side declares the counterparty payment method, amount, and — for crypto legs — the buyer's receiving address on the destination chain. These parameters become part of the deal record in the database, not just a chat message that could be edited or deleted.
The seventeen supported methods span seven networks:
| Network | Tokens | Verification source |
|---|---|---|
| Tron | USDT (TRC-20), native TRX | TronGrid API |
| Ethereum | USDT, USDC (ERC-20), native ETH | Etherscan v2 API |
| BSC | USDT, USDC (BEP-20), native BNB | Public JSON-RPC node |
| Polygon | USDT, USDC | Etherscan v2 (Polygon) |
| Arbitrum | USDT, USDC | Etherscan v2 (Arbitrum) |
| Base | USDC | Blockscout REST v2 (keyless) |
| TON | USDT (Jetton), native TON | TON API |
| Bitcoin | BTC | Public mempool API |
| Litecoin | LTC | Public explorer API |
USDC-TRC20 was intentionally excluded — Circle deprecated it. The list is designed to cover the networks where actual OTC volume happens, not every conceivable chain.
2. The seller declares a transaction ID
After sending the counterparty payment, the seller enters the transaction hash into the deal's structured payment message. This isn't just a chat text blob — it's stored as a server-side field on the deal record, paired with the declared method and amount.
Not every crypto leg triggers automated verification. If the method is in the supported matrix above, the txid feeds into the live check. If it's "other crypto" — say, Solana or Monero — the claim still gets written to the deal record, but verification stays manual (chat plus explorer). Fiat payments have no server-side fields at all; they're entirely end-to-end encrypted.
3. The pipeline checks the chain
The verification module picks up the declared txid and queries the appropriate blockchain API. What it checks depends on the network:
- For token transfers (USDT, USDC): the module verifies that the specific token contract emitted a transfer event of the declared amount — or greater — to the buyer's address. Contract addresses and decimals are canonical constants inside the module, not user-supplied, which prevents spoofing through fake token contracts.
- For native transfers (ETH, BNB, TRX, TON, BTC, LTC): it checks the transaction output or receipt for the correct recipient and value.
- Confirmation thresholds vary by chain. As the Kaspa wiki explains, Kaspa uses DAA score as its global clock for measuring block maturity; the verification pipeline applies analogous per-chain confirmation requirements to balance speed against finality risk.
API access varies by chain. EVM chains (Ethereum, Polygon, Arbitrum) require an Etherscan v2 API key; without it, those specific methods are unavailable — except Base, which uses the keyless Blockscout REST v2 endpoint, and BSC, which hits a public JSON-RPC node. Tron, Bitcoin, Litecoin, and TON use their own public or self-hosted APIs and always work. A kill-switch disables the entire module if an API dependency becomes unreliable.
4. Status badge appears for both sides
The result feeds into a status machine with seven states:
awaiting → declared → pending_conf → verified
→ mismatch
→ failed
→ not_found
→ error
awaiting: deal is funded, seller hasn't declared a txid yet.declared: txid entered, not yet checked.pending_conf: transaction found, waiting for sufficient confirmations.verified: confirmations met, amount and recipient match deal terms.mismatch: transaction found, but amount or recipient doesn't match.failed: transaction exists on-chain but reverted or failed.not_found: no transaction with that hash on the declared network.error: API unreachable or returned an unexpected response.
Both the buyer and seller see this status when they poll the deal state. It's a real-time signal — the pipeline re-queries as confirmations accumulate, so a pending_conf will eventually resolve to verified.
What verification does not do
This is the critical distinction. The verification is advisory-only.
It does not modify the escrow.sil contract. The contract has no concept of cross-chain state. Its ten spending paths remain exactly the same, and the single-input invariant is untouched.
It does not auto-release funds. Even if verification shows verified, the buyer still has to manually sign the release transaction. The contract enforces this — no server action can bypass it.
It does not replace disputes. If verification shows mismatch, it's a strong signal — but dispute resolution (chat key reveal, AI forensics, human arbiter) is still the binding mechanism for contested deals. The verification status becomes one piece of evidence in the dispute transcript, alongside chat messages and media attachments.
Think of it as a second pair of automated eyes. The contract is the judge; verification is the evidence camera.
How it fits the deal lifecycle
In practice, an OTC deal flows like this:
1. Create — the initiator sets up the deal, choosing the OTC template and declaring counterparty terms (e.g., "I will send 500 USDT on Tron to address T..."). 2. Join — the counterparty joins via a one-time code. The escrow address is computed from both parties' public keys. 3. Fund — the KAS side sends funds to the escrow address. The watcher detects the UTXO and marks the deal as funded. 4. Counterparty payment — the seller sends crypto on the other chain and submits the txid through the structured payment message. 5. Verification runs — the pipeline checks the chain and updates the status. Both sides see the badge in their deal panel. 6. Release — if satisfied (whether by verified status, manual explorer check, or trust), the buyer signs release. KAS flows to the seller.
If verification shows mismatch, the buyer has clear reason to pause before releasing. The dispute flow then takes over, with the verification status recorded as part of the evidence.
Kaspa Escrow puts funds in an on-chain contract, not with a middleman. Cross-chain verification adds a live, automated check on the counterparty leg — advisory, but far better than blind trust. If you trade peer-to-peer, try Kaspa Escrow and see the verification status badge in your next deal.
Trade-offs and honest limitations
No design is without compromises.
Advisory, not binding. The contract cannot enforce cross-chain conditions. A determined counterparty could theoretically send a valid-looking transaction that gets verified on the explorer but has some edge-case issue — a token transfer reverted at the next block on a chain with probabilistic finality, for instance. Confirmation thresholds mitigate this but don't eliminate it. Finality guarantees vary by chain, and the pipeline reflects that uncertainty honestly.
API dependency. Verification relies on third-party APIs — Etherscan, TronGrid, Blockscout, public nodes. If an API is rate-limited, down, or returns stale data, the status degrades gracefully to error or not_found. The deal isn't blocked, but the signal is absent. A kill-switch lets operators disable the feature entirely if a dependency becomes unreliable.
Fiat is untouched. Bank transfers, cash-in-person, and other fiat methods have no on-chain footprint to verify. They remain entirely peer-to-peer through the encrypted chat. Automated fiat verification would require bank API integrations that introduce custodial risk and regulatory complexity — the opposite of what Kaspa Forge is built for.
"Other crypto" stays manual. If the counterparty payment is on a network not in the seventeen-method matrix, the deal still works — the seller can declare a txid and the buyer can check it independently — but there's no automated status badge. Adding new networks is a code change, not a configuration toggle.
Etherscan key requirement. For the four EVM chains using Etherscan's v2 API, the feature requires a funded API key at the operator level. Without it, those specific methods are unavailable (except Base via Blockscout and BSC via public RPC). This is an operational dependency, not a protocol limitation.
Why this matters for self-custody
The broader point isn't just about one feature. It's about the gap between what on-chain contracts can enforce and what real-world trades require. Kaspa's covenants give strong programmable guarantees within the Kaspa UTXO set — but the moment a trade crosses chains, we're back to the traditional problem of trust and verification.
The cross-chain verification pipeline doesn't solve cross-chain trustlessness. That would require atomic swaps or bridges, each with their own complexity and risk surfaces. What it does is reduce the verification burden on individual traders from "check the right explorer, find the right token contract, parse the receipt, hope you didn't miss something" to "look at a status badge." The contract remains the source of truth for the KAS side. The badge is a tool, not a replacement for judgment.
For the Kaspa ecosystem, it's one more step toward making peer-to-peer trading practical without custodians — built on the same on-chain covenant infrastructure that powers Kaspa Safe and the rest of the platform.
FAQ
Does the escrow contract enforce the counterparty payment?
No. The escrow.sil contract only controls the KAS side. Verification is advisory — it gives both sides a live status badge, but release still requires the buyer's manual signature.
Which chains and tokens are supported?
Seventeen methods across Tron, Ethereum, BSC, Polygon, Arbitrum, Base, TON, Bitcoin, and Litecoin — covering USDT, USDC, BTC, LTC, and native tokens. The list grows with code updates.
What happens if a blockchain API is down?
Verification degrades to "error" or "not_found". The deal itself is unaffected — funds stay in the on-chain escrow, and the buyer can still verify manually on an explorer.
Is fiat payment verification supported?
No. Fiat legs (bank transfer, cash) are entirely peer-to-peer through end-to-end encrypted chat. There is no automated server-side verification for fiat.
Can the server steal funds through the verification module?
No. The server never holds funds or signing authority. Verification is a read-only check against public blockchain APIs. The contract's spending paths are unchanged.
Put your KAS where theft can be cancelled
A covenant vault on Kaspa mainnet: your keys, your rules, our tooling. Free on-chain, forever.
Create a vault
