Skip to content
Bearer

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

  1. run 1
    5.8 s
  2. run 2
    4.3 s
  3. run 3
    4.5 s
  4. run 4
    4.7 s
  5. run 5
    4.6 s
  6. run 6
    4.0 s

Send → final (wait_until FINAL), timed from a laptop

Base withdrawal

withdraw_evm through the contract · secp256k1 (domain 0)

7.7 smedian · N = 5

  1. run 1
    8.4 s
  2. run 2
    7.5 s
  3. run 3
    7.7 s
  4. run 4
    7.4 s
  5. run 5
    7.7 s

Submit → signed transaction visible in the contract's view

Ed25519 signature

the signer's Solana domain (domain 1), called directly

8.0 smedian · N = 5

  1. run 1
    8.1 s
  2. run 2
    7.4 s
  3. run 3
    7.7 s
  4. run 4
    8.0 s
  5. run 5
    8.0 s

Submit → final outcome with the signature

Bitcoin withdrawal

withdraw_btc, 1 → 4 inputs joined into one callback

6.5 s–8.4 sone run each · N = 4

  1. 1 input
    8.4 s
  2. 2 inputs
    6.5 s
  3. 3 inputs
    7.8 s
  4. 4 inputs
    7.1 s

Submit → signed transaction visible in the contract's view

Solana withdrawal

withdraw_sol through the contract · Ed25519 checked on-chain

8.0 smedian · N = 2

  1. run 1
    8.3 s
  2. run 2
    7.7 s

Submit → signed transaction visible in the contract's view

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

  1. N

    finishr.testnet hands sealed vault No. 0006, holding 684,666 sats of testnet Bitcoin, to takaba.testnet. One NEAR transaction.

    handover
  2. 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
  3. N

    takaba.testnet breaks the seal and asks for a Bitcoin withdrawal, in one transaction, then for a Solana one.

    open
  4. 300,000 sats reach sealed vault No. 0009, with the change back to No. 0006. Confirmed in testnet4 block 160,228.

    bitcoin
  5. 0.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…20e3

Bitcoin 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…58b6

Solana devnet

Confirmed on-chain

Vault No. 0002 → itself, 1,000 lamports · signed in 7.7 s · finalized in slot 520,280,234

jQCk6nNL…grmt

The 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 input
    2.8 Tgas
  • 2 inputs
    3.3 Tgas
  • 3 inputs
    3.9 Tgas
  • 4 inputs
    4.4 Tgas
usedreserved (30 Tgas)

Whole withdrawal vs NEAR's limit

Every receipt in the transaction, signer included, against the 300 Tgas a NEAR transaction may carry.

  • 1 input
    15.1 Tgas
  • 2 inputs
    24.2 Tgas
  • 3 inputs
    33.4 Tgas
  • 4 inputs
    42.6 Tgas
measured300 Tgas limit

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_transfer
    ProvenBase, 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_call
    Proven
  • 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_signature
    Proven
  • 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_break
    Proven
  • T5

    Transfer while a withdrawal is being signed

    A signature in flight means the vault is opened, which refuses transfers

    transfer_rejected_during_pending_signature
    Proven
  • 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 params
    ProvenBase, 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_chain
    Proven
  • 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 withdrawal
    ProvenBase, 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_keys
    Partly
  • 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 empty
    Proven
  • 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 path
    By 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 path
    By design
  • T16

    Deposits on the wrong network

    Warnings in the deposit flow; the contract signs only for Base Sepolia

    Copy and review, no code path
    By 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 cases
    ProvenBase, 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 path
    By 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 rerun
    Proven
  • M1

    Fake a listing by calling the market's nft_on_transfer directly

    Only the Bearer contract may call it

    only_bearer_can_list
    Proven
  • 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_sale
    Proven
  • 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_buyer
    Proven
  • M4

    A payout bounces and the money is lost

    Kept as a claimable balance for whoever holds the account name

    bounced_payout_becomes_claimable
    Proven
  • 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_listing
    Proven
  • 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_vault
    Proven
  • M7

    Someone else delists, or a delisted vault is bought

    Only the seller delists; delisting removes the listing

    only_the_seller_can_delistbuy_after_delist
    Proven
  • 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 vault
    Proven
  • 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_schedule
    Proven
  • S2

    Release a scheduled vault before its date

    release refuses until the block time reaches the date

    release_waits_for_the_date
    Proven
  • S3

    Release it to someone other than the recipient

    The recipient is fixed when scheduling; release takes no recipient

    anyone_can_release_on_the_date
    Proven
  • 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_date
    Proven
  • 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_vault
    Proven
  • 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_scheduled
    Proven
  • 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_vault
    Proven
  • S8

    A handover stops halfway

    Gas floors; callbacks never panic and put the schedule back to waiting

    failed_move_keeps_the_schedule
    Proven
  • S9

    A vault sent without a schedule is stuck

    return_unscheduled sends it back to the holder before the schedule

    return_unscheduled tests
    Proven
  • 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 review
    By 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.toml
  • Sandbox tests (bitcoinjs-lib, noble and @solana/web3.js check every signature)

    pnpm test:contracts
  • Testnet signing spike against the real MPC signer

    cd contracts/tests && pnpm spike:testnet run
What you're still trusting