Order on Starknet, write on Bitcoin, get money trustlessly, repeat
Broly is a decentralized Bitcoin inscription service that uses Starknet for orderbook management. It enables trustless Bitcoin inscriptions with guaranteed payments through smart contracts.
This codebase is an experimental PoC as part of Bitcoin explorations at StarkWare, and has not undergone a professional audit.
Broly is a showcase of the power of Starknet brought to the Bitcoin ecosystem. With Broly, a Requester
without any funds on Bitcoin can get their data inscribed on Bitcoin for a STRK
fee. All the Requester
needs is a Bitcoin and a Starknet wallet extension. The Requester needs STRK
on Starknet, but does not need any BTC
on the Bitcoin network. The Requester
broadcasts the request transaction to Starknet with data. The data is stored in the Broly contract. A Submitter
running the inscribor
service can pick up the request, inscribe the data on Bitcoin, and transfer it to the Requester
's Bitcoin address. The Submitter
can submit the creation and transfer transactions to the Broly contract on Starknet, and get the full verification of the correctness of the transaction execution, transaction inclusion in the block, and the inclusion of the block in the canonical chain.
Try Broly!
Requester
connects Starknet wallet extension: Argent or Braavos. ClickLogin
in the top right corner.Requester
getsSTRK
testnet tokens from the Starknet Foundation faucet.Requester
creates an inscription order:- Specifies inscription content (data) as message (text) or from a set of predefined emojis.
- Clicks
Inscribe
and connects pop up Bitcoin Xverse wallet. - Reward amount in
STRK
is calculated automatically based onBTC
/STRK
price. - Bitcoin Taproot compatible address is automatically fetched from Xverse connected wallet.
- Order is created and stored in the Broly contract.
Requester
's funds are locked in the Broly contract.- A
RequestCreated
event with theinscription_id
,caller
,receiving_address
, andfee
is emitted. - The open request info is stored in the Broly database and is visible on the website at
https://www.broly-btc.com/request/{inscription_id}
. - The Requester is able to cancel the request and get the funds back.
- A
RequestCanceled
event with theinscription_id
is emitted. - It is not possible to predict how fast an inscription and a transfer transaction will be included in a Bitcoin block. Even though Starknet L2 is blazing fast and cheap, this is not the case with Bitcoin in 2025. It's strong security properties require waiting for a miner to pick up a transaction, include it in a block, do the proof of work, and submit it to the blockchain. The
Requester
has to wait for theSubmitter
to get at least 1 confirmation for each transaction. For 2 sequential transactions (you can send the inscription only after it has been insribed) it may take between 15 minutes and over an hour.
- Locking inscriptions:
- A
Submitter
runs theinscribor service
which picks up open requests by the ID of the open order. - A
RequestLocked
event with theinscription_id
is emitted. - Order status changes to
Locked
on Broly website and in the Broly contract. - The lock is valid for 100 Starknet blocks. Within those 100 blocks, the
Submitter
has to create the inscription and transfer it to theRequester
's address on Bitcoin. - The
Requester
cannot cancel the inscription if the lock has not expired. - Another
Submitter
can only lock the inscription again if the lock has expired. - Note that the Starknet wallet (in root
.env
) used to lock the inscription must be the same as the Starknet wallet used to submit the inscription (inbitcoin-on-starknet.js/.env
).
- A
- Inscribing on Bitcoin:
The
inscribor service
runsord
(see Installation Guide) to deliver the inscriptions to the expected Bitcoin address. Theord
wallet doing the inscription must have a UTXO that has enough satoshis for the postage and for the fee. The defaultpostage
value is 546sat,fee-rate
is satoshis per byte. - Submitting proof in inscription on Starknet:
The
bitcoin-on-starknet.js
package:- Fetches the Bitcoin data from the creation and transfer Bitcoin transactions.
- Registers the Bitcoin blocks and updates the canonical chain with the Utu Relay contract on Starknet.
- Serializes it for
submit_inscription
to the Broly contract on Starknet. - Triggers
STRK
reward release to theSubmitter
on successful inscription. - Order status changes to
Closed
on Broly website and in the Broly contract. - A
RequestCompleted
event withtx_hash
andinscription_id
is emitted. Can be used manually if for some reason an inscription was locked, but the inscription on Bitcoin failed (e.g. due to low funds) and was made withord
directly.
Requester
owns the inscription on Bitcoin,Submitter
receives reward on Starknet.
- Run the app
cp .env.example .env
# Edit .env variables to match your environment
docker compose up
View the website locally.
- Restart your app ( after changes to backend(s), indexer, ... )
docker compose down --volumes
docker compose build
docker compose up
Head to the Broly website.
Ensure that you have a Starknet wallet extension: Argent or Braavos with funds (on https://sepolia.starkscan.co/ testnet, where the Broly contract is currently deployed). Choose Image/Message/Gif, upload your inscription data, approve the transaction and wait for a Submitter
to complete your request.
For a Submitter
: Interacting with the scripts to fetch open requests, lock and submit transactions on Starknet
Run
cp ./packages/bitcoin-on-starknet.js/.env.example ./packages/bitcoin-on-starknet.js/.env
To ensure successful runs of all the scripts, you will need bun
, sncast
, and ord
.
Create an account and get a Bitcoin endpoint and a key at Quicknode. Fill out the Bitcoin environment variables. This is needed to fetch the necessary data from the Bitcoin provider.
Install bun
from bun docs.
Install Starknet foundry.
Create a Starknet account using sncast
. The name of the account will be passed to the scripts that interact with Starknet, and the address and private key for the Starknet provider environment variables.
Ensure that your ord server
is synced and running. Syncing ord
from scratch can take over a week, so make sure to use pre-built indices as shared in the Ordicord
Discord server. Note that the ord server
requires the Submitter
to run a Bitcoin full node, or use RPC connection. Bitcoin Core client (version 28.0 or above) can be downloaded and run on a remote machine or locally and requires around 600GB initial download of data. An option for running a Bitcoin node is a Digital Ocean droplet, which allows for one click deployment and SSH connection.
Ensure you have a Bitcoin wallet in ord
with enough satoshis. You can send BTC from any wallet, but make sure to send it to the taproot address starting with bc1
.
Create or restore a Bitcoin address. Usage:
ord wallet create --help
or
ord wallet restore --help
Run
export BTC_RPC_USER=user
export BTC_RPC_PASS=password
export BTC_RPC_URL=http://33.333.333.333:8332
export SN_ACCOUNT=account_name
./packages/scripts/automate_inscriptions.sh $SN_ACCOUNT $BTC_RPC_USER $BTC_RPC_PASS $BTC_RPC_URL
Every inscription requires an unspent UTXO
to be used as an input to the transaction. If a Submitter
does not have an available UTXO
, the insciption transaction will not go through. Sometimes this happens because the change is part of the transaction that has not been confirmed yet. If you want to run the Submitter
script so that it processes open requests in parallel, you need to ensure you have enough UTXO
s. Currently the script processes open requests sequentially.
broly/
├── apps/
│ ├── web/ # Frontend React application
│ └── backend/ # REST API service
├── packages/
│ ├── onchain/ # Starknet smart contracts
│ ├── scripts/ # Deployment & Testing scripts
│ └── indexer/ # Starknet contract indexing
│ └── infra/ # Deployment configs
│ └── regtest/ # Scripts for Bitcoin regtest testnet
│ └── bitcoin-on-starknet.js/ # Bitcoin data scripts
├── .github/
│ ├── workflows/ # GitHub workflows
├── package.json
└── turbo.json
└── docker-compose.yml
- Frontend:
- React + TypeScript
- Vite
- TailwindCSS
- Starknet.js
- BitcoinJS-lib
- Backend:
- Golang
- Postgres DB
- REST API
- Smart Contracts:
- Cairo (Starknet)
- Scarb
- Inscribor:
ord
command-line wallet
- New inscription order form
- Dashboard view for pending inscriptions
- Wallet connections (Bitcoin + Starknet)
- Order status tracking
- Exploring inscriptions
- REST API for order management
- Status tracking endpoints
- Order history
- Broly (Orderbook) contract
- Transaction inclusion
- Utu Relay contract
- Raito light client
ord
CLI scripts- Bitcoin inscription creation
- Transaction verification
- Starknet interaction for reward release
flowchart TB
subgraph Frontend
UI[React UI]
BW[Bitcoin Wallet]
SW[Starknet Wallet]
end
subgraph Backend
API[REST API]
DB[(Database)]
end
subgraph Starknet
OB[Orderbook Contract]
TI[Tx Inclusion]
UR[Utu Relay]
RA[Raito]
end
subgraph Bitcoin
BTC[Bitcoin Network]
end
subgraph Inscribor
IS[Inscription Service]
OM[Order Monitor]
ORD[Ordinals CLI]
end
UI --> API
UI <--> BW
UI <--> SW
API --> DB
SW <--> OB
ORD --> BTC
OM --> OB
OB --> TI
TI <--> UR
UR <--> RA
API --> OM
OM --> IS
IS --> OB
Fraud detection
: will be implemented for the Utu Relay contract. A user who is aware of a longer chain with more proof of work needs to be able to override a false block.ZK proofs
: currently the inscribed data is stored onchain, and it is passed for verification inside the serialized Bitcoin transaction. The issue with it is that a large enough image in calldata can easily fill up the block. The solution is to have a ZK proof that the data is included in the witness field of the Bitcoin transaction.Configurable security parameters
: aRequester
needs to be able to set the number of confirmations that the transfer transaction got. Currently it's accepted if there is one or more confirmations.Configurable fees
: currently theSTRK
fee is calculated automatically based on theSTRK
/BTC
price. In the future aRequester
will be able to addSTRK
to incentivize theSubmitter
.
- The verification of Bitcoin transactions is possible thanks to the Exploration Team at Starkware. Raito, a Bitcoin light client written in Cairo, and
shinigami
: A Bitcoin script VM, aka Bitcoin Execution Engine written in Cairo. - The verification of the transaction inclusion in the block and maintaining the canonical chain is possible thanks to the LFG labs team and their work on Utu Relay.
- The debugging of the verification flow was possible thanks to the Walnut team and their transaction debugger.
Broly is licensed under the MIT License. See the LICENSE file for details.