Skip to main content
BRC2.0 offers powerful Bitcoin-native smart contract capabilities, but it operates under real constraints. This page covers every known limitation that affects contract behavior and dApp design. Read this before you start building.

Latency: ~10-minute block times

Execution depends on Bitcoin block confirmation. Unlike Ethereum (which targets ~12-second blocks), Bitcoin targets ~10 minutes per block. This means:
  • Contract calls are not instantaneous
  • Users should expect multi-minute delays between submitting an action and seeing its effect
  • You cannot build synchronous, sub-second UX flows on top of BRC2.0 directly
Do not design user flows that assume fast finality. A transaction submitted right after a Bitcoin block was found may wait close to 10 minutes before inclusion. Design all user-facing interfaces for asynchronous flows with optimistic UI updates and clear status indicators.

No synchronous Bitcoin state queries

Contracts cannot query Bitcoin state in real time. All operations are based on indexed, confirmed inscriptions. This means:
  • You cannot read a UTXO balance or check a Bitcoin transaction within a contract call as if it were a synchronous RPC call
  • Any logic that depends on Bitcoin state must work from data that was already indexed and included in a prior inscription
Do not write contract logic that assumes instant UTXO or balance visibility. Any Bitcoin-state-dependent condition must be satisfied through an earlier, already-confirmed inscription. Assumptions of real-time Bitcoin data will lead to incorrect or permanently broken logic.

Indexer determinism requirements

Contract state is reconstructed by deterministic replay of inscriptions in order. Every compliant indexer that processes the same Bitcoin history must arrive at identical contract state. For you as a developer, this means:
  • Contracts must not produce non-deterministic outputs (no randomness from block hashes, timestamps, or external inputs that vary between replays)
  • Execution order is strictly sequential — there is no out-of-order or parallel execution
  • Reorgs cause execution to be replayed from the reorg point; your contract logic must be safe to re-execute
This is conceptually similar to Ethereum replay tests, but the underlying ordering chain is Bitcoin. If your contract behaves correctly under Ethereum replay conditions (deterministic, no side effects from execution order), it will behave correctly here.

block.timestamp unreliability

block.timestamp in BRC2.0 reflects Bitcoin block timestamps. Bitcoin miners have latitude to set block timestamps within a range (subject to consensus rules), making them less reliable than Ethereum block timestamps for precision timing.
Do not use block.timestamp for precision timing, randomness, or short time windows. Bitcoin block timestamps can be slightly in the past or future relative to wall-clock time. For coarse time windows (hours, days), they are generally reliable. For sub-minute precision, they are not.

No msg.value in native ETH

There is no native ETH in BRC2.0. The system operates on BRC-20 tokens, not ETH. This means:
  • msg.value is always zero
  • Payable functions that expect ETH will not receive it
  • Native ETH transfers between contracts are not supported
Do not use msg.value, payable, or ETH transfer patterns (address.transfer(), address.call{value: ...}()). These patterns compile without error but will not behave as intended. Use BRC-20 token balances and explicit transfer logic instead.

ecrecover is not usable

EVM addresses in BRC2.0 are derived from Bitcoin pkscripts and have no associated ECDSA private keys. ecrecover cannot be used for authentication.
Any contract that calls ecrecover for authentication will either return a meaningless address or fail to verify legitimate users. Replace all uses of ecrecover with the BIP-322 verification precompile. See Accounts & Identity for the correct pattern.

No EVM mempool

There is no EVM mempool. Transactions cannot be submitted to a peer-to-peer EVM network, monitored in a pending state, or replaced using EIP-1559-style replacement.
  • There is no eth_sendRawTransaction
  • There is no “pending” transaction state to query
  • Transaction replacement (speed-up, cancel) works through Bitcoin transaction replacement (RBF), not EVM mechanisms

tx.origin is unreliable

There is no concept of a user-controlled EOA originating a call chain. tx.origin does not represent a reliably user-controlled address.
Do not use tx.origin for authorization or security checks. It is not equivalent to a user’s identity and can be spoofed or misinterpreted in this environment.

Gas-price-based logic does not apply

There is no dynamic gas price, base fee, or priority fee. Contracts that use gas-price-based logic for anti-front-running, fee estimation, or dynamic pricing will not behave as intended.
Do not use tx.gasprice or block.basefee in contract logic. These values are meaningless in BRC2.0 and will not reflect actual costs.

Limitations at a glance

LimitationImpactMitigation
~10-minute block timesNo fast finalityDesign async UX with optimistic updates
No synchronous Bitcoin queriesCan’t read UTXOs in real timeUse pre-indexed inscription data
Indexer determinismMust be deterministic, sequentialAvoid randomness and order-dependent logic
block.timestamp unreliableNo sub-minute timingUse coarse time windows only
No msg.value / ETHETH transfers don’t workUse BRC-20 token logic
ecrecover unusableEthereum auth patterns breakUse BIP-322 precompile
No EVM mempoolNo pending tx visibilityInteract through Bitcoin inscriptions
tx.origin unreliableAuth bypass riskUse msg.sender + BIP-322
No dynamic gas priceGas-price logic breaksRemove all tx.gasprice usage