Skip to content

lana-shanghai/broly

 
 

Repository files navigation

broly-logo

B.R.O.L.Y.

Bitcoin Registry Orchestrates Like Yesterday

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.


Disclaimer

This codebase is an experimental PoC as part of Bitcoin explorations at StarkWare, and has not undergone a professional audit.

Why Broly?

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!

Diagram

broly-diagram

Flow

  1. Requester connects Starknet wallet extension: Argent or Braavos. Click Login in the top right corner.
  2. Requester gets STRK testnet tokens from the Starknet Foundation faucet.
  3. 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 on BTC / 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 the inscription_id, caller, receiving_address, and fee 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 the inscription_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 the Submitter 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.
  4. Locking inscriptions:
    • A Submitter runs the inscribor service which picks up open requests by the ID of the open order.
    • A RequestLocked event with the inscription_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 the Requester'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 (in bitcoin-on-starknet.js/.env).
  5. Inscribing on Bitcoin: The inscribor service runs ord (see Installation Guide) to deliver the inscriptions to the expected Bitcoin address. The ord wallet doing the inscription must have a UTXO that has enough satoshis for the postage and for the fee. The default postage value is 546sat, fee-rate is satoshis per byte.
  6. 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 the Submitter on successful inscription.
    • Order status changes to Closed on Broly website and in the Broly contract.
    • A RequestCompleted event with tx_hash and inscription_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 with ord directly.
  7. Requester owns the inscription on Bitcoin, Submitter receives reward on Starknet.

Running Broly locally for tests and development

  1. Run the app
cp .env.example .env
# Edit .env variables to match your environment
docker compose up

View the website locally.

  1. Restart your app ( after changes to backend(s), indexer, ... )
docker compose down --volumes
docker compose build
docker compose up

For a Requester: Interacting with Broly as a user in one click

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 UTXOs. Currently the script processes open requests sequentially.

Project Structure

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

Technology Stack

  • 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

Components

Frontend (web)

  • New inscription order form
  • Dashboard view for pending inscriptions
  • Wallet connections (Bitcoin + Starknet)
  • Order status tracking
  • Exploring inscriptions

Backend (backend)

  • REST API for order management
  • Status tracking endpoints
  • Order history

Smart Contracts (onchain) and dependencies

  • Broly (Orderbook) contract
  • Transaction inclusion
  • Utu Relay contract
  • Raito light client

Inscribor Service

  • ord CLI scripts
  • Bitcoin inscription creation
  • Transaction verification
  • Starknet interaction for reward release

Architecture

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
Loading

Future development

  • 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: a Requester 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 the STRK fee is calculated automatically based on the STRK/BTC price. In the future a Requester will be able to add STRK to incentivize the Submitter.

Credits

  • 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.

License

Broly is licensed under the MIT License. See the LICENSE file for details.

About

Order on Starknet, write on Bitcoin, get money trustlessly, repeat

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 47.2%
  • Cairo 19.6%
  • Go 18.6%
  • Shell 6.6%
  • CSS 5.2%
  • JavaScript 1.3%
  • Other 1.5%