Proof
Don't trust us. Check.
Every claim on this site, with the evidence behind it: live answers from NEAR testnet that your browser fetches itself, numbers we measured against NEAR's real MPC signer (each with how many runs), and every attack we know of with the test that stops it.
- Chains signed by NEAR's MPC
- 3 of 3Bitcoin, Base and Solana on testnet
- Signatures measured
- 16against v1.signer-prod.testnet, 8–9 Nov 2026
- Landed on another chain
- 3confirmed on Base Sepolia, Bitcoin testnet4 and Solana devnet
- Threats proven by tests
- 33 of 39the rest are partly done, by design, or not yet
01
Live from NEAR testnet
Run in your browser against a public RPC. Nothing here comes from a Bearer server.
Asking NEAR testnet…
02
Timed on testnet
Every bar is one real transaction on testnet, timed from submitting it. The handover ran on bearer.testnet and needs no signature; the withdrawals were signed by NEAR's MPC network on the spike contract (v3a.bearer-1108-ffb3.testnet). Click a time to see its transaction.
Sealed handover
nft_transfer of vault No. 0007 on bearer.testnet, alice ↔ bob · nothing moves on Bitcoin, Base or Solana · 0.0004 NEAR in gas each
4.6 smedian · N = 6
Base withdrawal
withdraw_evm through the contract · secp256k1 (domain 0)
7.7 smedian · N = 5
Ed25519 signature
the signer's Solana domain (domain 1), called directly
8.0 smedian · N = 5
Bitcoin withdrawal
withdraw_btc, 1 → 4 inputs joined into one callback
6.5 s–8.4 sone run each · N = 4
03
Where the withdrawals landed
A signature only matters once the other chain accepts it. The first run used the locked contract and real wallets; the three cards after it used the spike contract (v3a.bearer-1108-ffb3.testnet), whose vault numbers are its own.
Locked contract · real wallets · real coins
Bitcoin that changed hands without a Bitcoin transaction
- N
finishr.testnet hands sealed vault No. 0006, holding 684,666 sats of testnet Bitcoin, to takaba.testnet. One NEAR transaction.
handover Nothing happens on Bitcoin. The vault's address shows two transactions ever: the deposit, and the new holder's withdrawal, which spends that same coin.
address- N
takaba.testnet breaks the seal and asks for a Bitcoin withdrawal, in one transaction, then for a Solana one.
open 300,000 sats reach sealed vault No. 0009, with the change back to No. 0006. Confirmed in testnet4 block 160,228.
bitcoin0.5 SOL reaches vault No. 0009. Finalized in devnet slot 520,527,063.
solana
Base Sepolia
Confirmed on-chain
Vault No. 0002 → itself, 0.000001 ETH · block 56,270,095 · receipt 2.0 s after broadcast
0xb347…20e3Bitcoin testnet4
Confirmed on-chain
Vault No. 0004, handed from alice to bob, opened and withdrawn in one NEAR transaction · signed in 6.5 s · block 159,948
ce01f9ff…58b6Solana devnet
Confirmed on-chain
Vault No. 0002 → itself, 1,000 lamports · signed in 7.7 s · finalized in slot 520,280,234
jQCk6nNL…grmtThe market's first sale
On the locked contract, bearer.testnet: vault No. 0004 for 0.1 NEAR. Listed by alice, bought by bob; the vault moved first and stayed sealed with 0 signatures, then alice received exactly 0.11 NEAR (price + listing deposit). 8.9 Tgas to list, 11.5 Tgas to buy.
Opened and withdrawn through a wallet
On the locked contract, bearer.testnet, vault No. 0005: The owner's wallet broke the seal and asked for a Base withdrawal in one NEAR transaction; 0.0002 ETH went to a separate address, confirmed on Base Sepolia in block 56,685,109.
Two signatures, one nonce (T10)
On the locked contract, bearer.testnet, vault No. 0001: Two Base withdrawals signed for the same nonce, as a retry could leave them, broadcast together. Base Sepolia confirmed one in block 56,635,535 and refused the other; sent again afterwards, it got “nonce too low”. Refused: 0xec7e7f860048c298ddfa502c01d1925e2f4e786d84354afc0d83334e702f8b60
04
Gas, measured
Bitcoin is the heaviest withdrawal: one signature per input, all checked in a single callback.
Callback gas: reserved vs used
The callback checks every signature, then builds the transaction. It reserves 30 Tgas so it can never run out.
- 1 input2.8 Tgas
- 2 inputs3.3 Tgas
- 3 inputs3.9 Tgas
- 4 inputs4.4 Tgas
Whole withdrawal vs NEAR's limit
Every receipt in the transaction, signer included, against the 300 Tgas a NEAR transaction may carry.
- 1 input15.1 Tgas
- 2 inputs24.2 Tgas
- 3 inputs33.4 Tgas
- 4 inputs42.6 Tgas
05
Every attack we know of
docs/THREAT_MODEL.md. A row is proven only when its test passes.
- T1
Former owner withdraws after transferring
withdraw_* and break_seal require the caller to be the owner
alice_cannot_withdraw_after_transferalice_cannot_break_seal_after_transferalice_cannot_withdraw_btc_after_transferalice_cannot_withdraw_sol_after_transferProvenBase, Bitcoin, Solana - T2
Transfer an opened vault, by any path
One transfer gate, which refuses opened vaults; no other code changes the owner
opened_vault_rejects_nft_transfernft_transfer_callProven - T3
Keep a signature for a sealed vault
No signature can be requested while sealed; the signer sees no call
sealed_vault_cannot_request_signature…_btc_signature…_sol_signatureProven - T4
Race break_seal against a transfer
Receipts run one at a time; whichever runs first wins, the other fails cleanly
race_break_then_transferrace_transfer_then_breakProven - T5
Transfer while a withdrawal is being signed
A signature in flight means the vault is opened, which refuses transfers
transfer_rejected_during_pending_signatureProven - T6
Bypass the gate: approvals, the transfer_call return leg, a forgotten path
No approvals extension; the return leg uses the gate; a test fails if any other code writes the owner
nft_approve_not_exposedsingle_owner_write_pathresolve_keeps_opened_vault_with_receiver (a receiver opens it in the callback, then asks for it back: it stays opened, with the receiver)Proven - T7
Make the contract sign arbitrary bytes
Typed withdrawals only, built in-contract: EVM native transfer, Bitcoin SIGHASH_ALL with change to the vault, Solana one system transfer with a recent blockhash
rejects_calldata_shapesbip143_native_p2wpkh_vectorrejects bad Bitcoin spendssol_single_transfer_onlyrejects bad Solana paramsProvenBase, Bitcoin, Solana - T8
Collide derivation paths to sign for another vault
Paths built only by the contract from sequential IDs and fixed chain tags
paths_unique_per_vault_and_chainProven - T9
A signer timeout or error leaves the vault stuck
The callback never panics; the record fails, the vault stays opened, a retry works
failed_signature_can_retrya failed Bitcoin signature fails the whole withdrawala failed Ed25519 signature fails the withdrawalProvenBase, Bitcoin, Solana - T10
Two signatures exist after a retry
Both pay the same owner and spend the same coins or nonce; at most one confirms
spike:testnet same-nonce on bearer.testnet: two signed Base withdrawals for nonce 0, Base Sepolia confirmed one and refused the other (9 Nov)pnpm demo:dry step 7 (Bitcoin: a simulated ledger accepts one of two spends of a coin)Proven - T11
Admin or upgrade powers
No admin, upgrade or raw-sign methods; full-access keys deleted; code hash published
no_privileged_methodsspike:testnet lock (bearer.testnet: 0 keys, 9 Nov)Proven - T12
Drain storage to freeze the contract
Every state-growing call pays; the custody log is capped at 16
create_deposit_covers_max_vaultcreate_vault_requires_gas_for_keysPartly - T13
A stale copy of a Bearer link takes the vault after it was passed on
A link is the key of the account holding the vault; passing it on moves the vault to another account, so an old copy controls an empty one
testnet, 10 Nov: vault No. 0010 through three links and on to an account; each earlier link read emptyProven - T14
A seller takes payment and never transfers
Out of scope: Bearer guarantees what you receive, not that someone pays you. Said on the How page
Copy and review, no code pathBy design - T15
Wrong display data from an indexer
Balances are labelled observed, with source and time; the contract never relies on them
Copy and review, no code pathBy design - T16
Deposits on the wrong network
Warnings in the deposit flow; the contract signs only for Base Sepolia
Copy and review, no code pathBy design - T17
The signer returns a signature for the wrong key
The callback checks every signature against the vault's own key before storing anything
rejects_signature_from_wrong_keywrong-key Bitcoin and Ed25519 casesProvenBase, Bitcoin, Solana - T18
Someone who sees a Bearer link takes the vault first
By design, like cash: the page says so and offers to move it out; the key stays after #, never sent to a server
Copy and review, no code pathBy design - T19
Passing a vault on, or making links, stops halfway and loses the new key
The new link is stored and saved before anything moves; every step checks what already happened, so it resumes
testnet, 10 Nov: a pass-on reloaded mid-move resumed and finished; a mint stopped after its vault was finished by a rerunProven - M1
Fake a listing by calling the market's nft_on_transfer directly
Only the Bearer contract may call it
only_bearer_can_listProven - M2
Sell an opened vault, or one the seller no longer holds
The vault arrives through Bearer's sealed-only gate and stays in escrow; the gate checks again as it moves to the buyer
opened_vault_cannot_be_listeda_signature_in_flight_blocks_the_saleProven - M3
Buyer pays and gets nothing, pays a different price, or races another buyer
Exact price; a sale in flight locks the listing; the vault moves before any money; a vault that didn't move refunds the buyer
sold_vault_moves_first_then_seller_is_paida_deposit_during_a_pending_sale_belongs_to_the_buyerbuy_needs_the_exact_pricedouble_buy_racefailed_move_refunds_the_buyerProven - M4
A payout bounces and the money is lost
Kept as a claimable balance for whoever holds the account name
bounced_payout_becomes_claimableProven - M5
Settlement stops halfway
Buying and delisting refuse under 60 Tgas; the callbacks never panic
buy_needs_gas_for_the_whole_settlementfailed_move_restores_the_listingProven - M6
Fill the market's storage for free
Each listing holds a 0.01 NEAR deposit checked against its storage, returned on sale or delisting
listing_holds_the_deposit_and_covers_its_storagelisting_without_deposit_returns_the_vaultProven - M7
Someone else delists, or a delisted vault is bought
Only the seller delists; delisting removes the listing
only_the_seller_can_delistbuy_after_delistProven - M8
A vault sent to the market without a listing is stuck there
return_unlisted sends it to the holder before the market, read from the custody log; never a listed vault
return_unlisted sends a stray vault backreturn_unlisted can't take a listed vaultProven - M9
The market account's key holder acts as the owner of a listed vault
No admin or upgrade methods; full-access keys deleted at the locked deploy; until then the site shows the key count
spike:market lock (bearer-market.testnet: 0 keys, 9 Nov)Proven - S1
Fake a schedule by calling the schedule's nft_on_transfer directly
Only the Bearer contract may call it
only_bearer_can_scheduleProven - S2
Release a scheduled vault before its date
release refuses until the block time reaches the date
release_waits_for_the_dateProven - S3
Release it to someone other than the recipient
The recipient is fixed when scheduling; release takes no recipient
anyone_can_release_on_the_dateProven - S4
Cancel what was promised
Only the giver, only if cancellable, only before the date
irrevocable_schedule_cannot_be_cancelledonly_the_giver_can_cancelno_cancelling_after_the_dateProven - S5
The recipient's name isn't registered, so a squatter gets the vault
release checks the account exists first; otherwise the vault stays
missing_recipient_keeps_the_vaultProven - S6
The giver withdraws while the vault is scheduled
The schedule holds the vault and never breaks seals
giver_cannot_withdraw_while_scheduledopened_vault_cannot_be_scheduledProven - S7
Fill the schedule's storage for free
Each schedule holds a 0.01 NEAR deposit, checked against its storage
schedule_holds_the_deposit_and_covers_its_storagescheduling_without_deposit_returns_the_vaultProven - S8
A handover stops halfway
Gas floors; callbacks never panic and put the schedule back to waiting
failed_move_keeps_the_scheduleProven - S9
A vault sent without a schedule is stuck
return_unscheduled sends it back to the holder before the schedule
return_unscheduled testsProven - S10
The schedule account's key holder acts as the owner of a scheduled vault
No admin or upgrade methods; full-access keys deleted at the locked deploy; the site shows the lock state
spike:schedule lock (bearer-schedule.testnet: 0 keys, 9 Nov)Proven - M10
A buyer reads an observed balance as a guaranteed value
Listings show balances as observations, with source, time and confirmation status
UI reviewBy design
06
Run it yourself
The same checks, on your machine. You need Rust, Node and pnpm.
Unit tests (vectors: BIP143, BIP173/350, RLP, low-S, Solana shortvec)
cargo test --manifest-path contracts/Cargo.tomlSandbox tests (bitcoinjs-lib, noble and @solana/web3.js check every signature)
pnpm test:contractsTestnet signing spike against the real MPC signer
cd contracts/tests && pnpm spike:testnet run