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!
Requesterconnects Starknet wallet extension: Argent or Braavos. ClickLoginin the top right corner.RequestergetsSTRKtestnet tokens from the Starknet Foundation faucet.Requestercreates an inscription order:- Specifies inscription content (data) as message (text) or from a set of predefined emojis.
- Clicks
Inscribeand connects pop up Bitcoin Xverse wallet. - Reward amount in
STRKis calculated automatically based onBTC/STRKprice. - 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
RequestCreatedevent with theinscription_id,caller,receiving_address, andfeeis 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
RequestCanceledevent with theinscription_idis 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
Requesterhas to wait for theSubmitterto 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
Submitterruns theinscribor servicewhich picks up open requests by the ID of the open order. - A
RequestLockedevent with theinscription_idis emitted. - Order status changes to
Lockedon Broly website and in the Broly contract. - The lock is valid for 100 Starknet blocks. Within those 100 blocks, the
Submitterhas to create the inscription and transfer it to theRequester's address on Bitcoin. - The
Requestercannot cancel the inscription if the lock has not expired. - Another
Submittercan 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 servicerunsord(see Installation Guide) to deliver the inscriptions to the expected Bitcoin address. Theordwallet doing the inscription must have a UTXO that has enough satoshis for the postage and for the fee. The defaultpostagevalue is 546sat,fee-rateis satoshis per byte. - Submitting proof in inscription on Starknet:
The
bitcoin-on-starknet.jspackage:- 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_inscriptionto the Broly contract on Starknet. - Triggers
STRKreward release to theSubmitteron successful inscription. - Order status changes to
Closedon Broly website and in the Broly contract. - A
RequestCompletedevent withtx_hashandinscription_idis 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 withorddirectly.
Requesterowns the inscription on Bitcoin,Submitterreceives reward on Starknet.
- Run the app
cp .env.example .env
# Edit .env variables to match your environment
docker compose upView the website locally.
- Restart your app ( after changes to backend(s), indexer, ... )
docker compose down --volumes
docker compose build
docker compose upHead 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 --helpor
ord wallet restore --helpRun
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 UTXOs. 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:
ordcommand-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
ordCLI 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: aRequesterneeds 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 theSTRKfee is calculated automatically based on theSTRK/BTCprice. In the future aRequesterwill be able to addSTRKto 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.

