尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Held: buyer protection for stablecoin payments on Tempo
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
Buyer protection for stablecoin payments on Tempo.
The buyer pays with a plain transfer from their own wallet. The chain holds the money until delivery, and a limited
arbiter contract can only release it to the merchant or refund the buyer.
Built for the Colosseum Crypto World's Fair, Tempo track.查看完整 README ↗Buyer protection for stablecoin payments on Tempo.
The buyer pays with a plain transfer from their own wallet. The chain holds the money until delivery, and a limited arbiter contract can only release it to the merchant or refund the buyer.
Built for the Colosseum Crypto World's Fair, Tempo track.
ReceivePolicyGuard. The policy's recovery authority is the HeldArbiter contract.HeldArbiter is the only party that can claim held funds, and it can only send them to two places:
| Action | Who can call it |
|---|---|
release | the buyer (confirming delivery) at any time; anyone after the protection window; only the resolver if disputed |
dispute | only the original payer, only inside the window, only once |
refund | the merchant (voluntary); the resolver if disputed; the payer themselves if they sent a token the merchant doesn't accept |
Every payment gets exactly one decision. No party can send held funds anywhere else, including the merchant, the resolver and Held.
Merchants open #/merchant, connect the wallet that will be their checkout address, sign in (a signed message,
no transaction) and run a one-time setup from that wallet: mine the checkout address's TIP-1022 salt in the browser,
register it, deploy their own HeldArbiter, and set the receive policy. Held's server then verifies the setup
on-chain before listing the merchant, including a byte-for-byte check that the arbiter is the genuine contract.
Buyers open the checkout link (#/pay/:id), pay from their own wallet, then confirm delivery or open a dispute.
Checkout links (#/buy/:id): a merchant makes a reusable link for one product at a fixed price; every buyer who
opens it gets their own protected order. The dashboard also gives a copy-paste "Pay with Held" button (plain HTML,
inline styles, no script) that works on any website builder.
Resolvers decide disputes at #/resolve: refund the buyer or pay the merchant, nothing else.
Sandbox (#/sandbox, testnet only): a shared, already-set-up Sandbox Shop so anyone can play merchant, buyer
and resolver in about two minutes, with no mining or wallet install. Its merchant and resolver use public testnet
keys (in network.json, set up by scripts/sandbox-setup.ts) that hold only test funds and are never offered on
mainnet. The server refuses to re-register the sandbox address with any other arbiter.
Held's server holds no keys and signs nothing. Every release, refund, dispute and resolution is signed by that party's own wallet, and the arbiter contract enforces who may do what.
contracts/HeldArbiter.sol the arbiter (one per merchant; recovery authority for that merchant's payments)
shared/ data types shared by server and web; HeldArbiter.json (ABI + bytecode)
server/ API, sign-in, on-chain merchant verification (merchants.ts), multi-merchant indexer
web/ React app: landing, merchant setup + dashboard, buyer page, resolver console
network.json network settings: chain, accepted stablecoin, default resolver, default window
docs/ test run logs
npm install && npm run compile
(cd web && npm install && npm run build)
npm run server # http://localhost:8787, then open #/merchant to set up a shop
foundryup -n tempo # Tempo's Foundry fork (forge 1.8.3+)
forge test # or: npm test
test/HeldArbiter.t.sol has 33 tests: 29 unit tests and 4 fuzz tests (512 runs each). They run on Tempo Foundry's
local EVM with the real protocol precompiles: TIP-20 tokens, TIP-403 receive policies, the ReceivePolicyGuard and
the virtual-address registry. Nothing is mocked; every held payment and claim goes through the same code as on
testnet. Coverage:
Mutation check: breaking the early-release rule makes 5 tests fail, and redirecting merchant refunds to the merchant
makes 3 fail. Log: docs/forge-test-run.log.
| Script | What it checks | Result |
|---|---|---|
npm run spike:day1 | contract as recovery authority: all rules + negative tests | 29/29 (log) |
npm run test:virtual | per-order virtual-address payments through the arbiter | 12/12 (log) |
npm run test:e2e | the real dApp: a new merchant sets up from its own wallet, sign-in, on-chain registration (fake and 1-byte-tampered arbiters refused), orders, release, merchant refund, dispute decided by the resolver's wallet | 24/24 (log) |
Buyers, merchants and resolvers each sign from their own wallet. The wallet picker offers:
accounts): pay,
confirm delivery and dispute. node e2e/tempo-wallet.ts creates a fresh Tempo Wallet account in a throwaway
Chrome for Testing profile (a CDP virtual authenticator stands in for Touch ID) and runs all three: 4/4
(log).node e2e/metamask.ts
loads real MetaMask 13.49.0 (official release, SHA256 verified) into a throwaway Chrome for Testing profile,
imports a fresh testnet-only seed generated in memory for that run (never stored or reused), and tests connect,
add network, switch network, pay, confirm delivery and dispute: 7/7 (log).Stablecoin checkout is going mainstream but still behaves like cash for the buyer. Stripe's stablecoin payments, the market leader, list "Dispute support: No": once sent, a payment can't be reversed, and if a merchant never delivers the buyer has no recourse.
Held's advantage: the chain itself holds the payment. The buyer just sends a plain transfer from their own wallet, and nobody (not the merchant, not Held) can move the money anywhere except back to the buyer or on to the merchant.
| Buyer's side | Who holds the money | Buyer protection | |
|---|---|---|---|
| Stripe stablecoin checkout | Redirect + connect a wallet | Stripe (custodial) | None ("Dispute support: No") |
| Circle Refund Protocol | approve + pay() on an escrow contract | Escrow contract | Yes |
| Stabledrop | Fund a smart-contract escrow | Escrow contract | Yes (1% flat) |
| Settld | Through the platform's API flow | Escrow contract | Yes (early access) |
| Held | A plain transfer from their own wallet | Tempo's protocol (ReceivePolicyGuard) | Yes |
Why this is only possible now: Tempo's receive policies (T6, June 2026) hold incoming transfers in a protocol-level guard that only a designated recovery authority can claim, and virtual addresses (T3) give every order its own deposit address. On other chains, protection means an escrow contract the buyer has to interact with.
The arbiter contract is the safety rule: it can only release to the merchant or refund the original payer, never anyone else. Each merchant deploys their own, and Held verifies it byte for byte, so held funds are non-custodial by construction.
We're not the first to see this gap (Circle, Stabledrop and Settld are all working on it). Held is the lowest-friction way to protected stablecoin checkout we know of.
HeldArbiter.sol.