Alkanes Metaprotocol
Alkanes is a smart-contract metaprotocol on Bitcoin. It lets developers deploy and run programmable contracts directly on Bitcoin's base layer, with no sidechain and no separate validator set. frBTC, DIESEL, and FIRE are all Alkanes tokens, and SUBFROST's custody logic is coordinated through the Alkanes indexer.
Where it sits
Alkanes builds on Protorunes, which extends the Runes protocol with programmable execution. The layering is:
Bitcoin → Runes → Protorunes → Alkanes
Because everything is anchored to Bitcoin blocks and validated by Bitcoin consensus, Alkanes contracts inherit Bitcoin's security. Contracts are written in Rust and compiled to WebAssembly (WASM), and are executed deterministically by the indexer, so every node that runs the protocol computes the same state.
Protostones and cellpacks
A Bitcoin transaction carries an Alkanes instruction as a protostone: a protocol message encoded in the transaction's OP_RETURN. A protostone can move tokens between outputs and invoke a contract.
To call a contract, the protostone carries a cellpack. A cellpack is a list of integers, LEB128-encoded, of the form:
[block, tx, opcode, ...args]
- The first two values,
[block, tx], are the AlkaneId of the contract you are calling (see below). - The next value is the opcode, which selects the contract method.
- The remaining values are the method's arguments.
This replaces the older, flat "calldata" model: the cellpack is a length-prefixed list of variable-width integers, not a fixed-size byte array.
AlkaneId
Every alkane is identified by the location where it was etched:
[block, tx]
that is, the block height and the transaction index within that block. Some low ranges are reserved for system contracts. In text, an AlkaneId is written block:tx.
Contract interface (ABI)
A contract declares its methods with a MessageDispatch enum, tagging each with an #[opcode(n)]. At build time this generates a __meta export describing the contract's methods, their opcodes, parameters, and return types. You can read that ABI back from any deployed contract through the meta view function, which is the canonical way to discover what a contract can do. See Reading Alkane Metadata.
Composing operations in one transaction
A single transaction can carry several protostones that run in order. A common pattern for a rich interaction is three protostones:
- Transfer the tokens a contract will consume to the outputs (and shadow outputs) it reads from.
- Mint (for example, mint DIESEL alongside the interaction).
- Call the contract, which receives the transferred tokens and performs the operation.
The tokens routed in step 1 land on shadow outputs, protocol-level outputs that are not real Bitcoin outputs but are addressable by the protocol. This lets a contract receive exactly the assets it should, which keeps each contract's execution isolated. The details of building these are in Build on SUBFROST.
Reading contract state
You do not read a contract's storage directly. Instead you call its view functions through the indexer:
simulateevaluates a call read-only and returns the result.tracereturns the execution trace for a call.- The newer
simulateprotostones,simulatetransaction, andsimulateblockviews return full execution traces (per protostone, with fuel used and touched storage) so you can preview exactly what a transaction or block would do before broadcasting it.
These are documented in the JSON-RPC reference.
Fuel
Contract execution has a compute budget called fuel. It is similar to gas on Ethereum in what it measures, and unlike gas in the way that matters most: fuel is free.
There is no fuel price, no fuel market, and no balance to top up. Each block carries a fixed fuel budget, and it is shared only among the transactions that actually invoke a contract: an ordinary payment neither receives a slice nor dilutes anyone else's. Among the transactions that do invoke one, the budget is split in proportion to size in bytes, with a floor so that even a small one can do useful work. So a lone contract call in a block has the entire budget available to it, not a sliver of it. Fuel a transaction does not spend goes back to the block for the next one. Nothing is charged, in any asset, at any point.
What you pay to get a transaction into a block is the ordinary Bitcoin miner fee: denominated in native BTC and priced per byte, exactly as it would be for a transaction that ran no contract at all. Network fees on Alkanes are always BTC, because they are simply Bitcoin transaction fees. There is no separate gas token to acquire before you can transact.
So the lever on your compute budget is your transaction's size, which you are already paying for in sats. Making a call more computationally expensive does not make it more expensive to send.
One caveat, for honesty: if a call ever needs more fuel than its slice allows, it fails, and the remedy is a larger transaction, which does cost more in miner fees. In that corner, bytes buy compute. It is a corner rather than a rule, because the budget is shared only among contract transactions and is therefore generous at present density.
Today on mainnet the budget is 1,000,000,000 fuel per block, with a per-transaction floor of 3,500,000. Both are consensus constants and can change at a protocol upgrade.
An operation that runs out of fuel fails; it does not silently cost more. View functions run with a high fuel ceiling, so read-only queries rarely hit the limit.
Protocol fees are a separate matter from network fees: wrapping and unwrapping BTC charges 0.1% today, and swapping charges a pool fee. Those are charged in the assets involved, and they have nothing to do with fuel.
Where to go next
- frBTC Peg & Custody: how custody is built on top of this.
- JSON-RPC reference: the view functions in detail.
- Reading Alkane Metadata: discover any contract's ABI.