Skip to main content
BRC2.0 provides precompiled contracts that expose Bitcoin-native functionality to Solidity contracts. These precompiles bridge Bitcoin’s UTXO model with BRC2.0’s account model, enabling hybrid applications that leverage both ecosystems. Each precompile is available at a fixed address within the EVM execution environment.
PrecompileAddressPurpose
BIP-322 Verifier0xFEVerify Bitcoin wallet signatures
BTC Transaction0xFDGet Bitcoin transaction details
Last Satoshi Location0xFCTrack individual satoshi locations
Locked PkScript0xFBCheck BRC-20 token holder locks
OP_RETURN TX ID0xFAGet the activating Bitcoin transaction ID

Verifies BIP-322 signatures, which are the generic Bitcoin message signing format. EVM addresses in BRC2.0 are generated from Bitcoin scripts and cannot sign messages directly — this precompile enables signature-based authorization using Bitcoin wallets instead.Use cases: Caller verification, authentication and authorization using Bitcoin wallets, Bitcoin identity verification.
// Precompile address: 0xFE

/**
 * @dev BIP322 verification method
 */
interface IBIP322_Verifier {
    function verify(
        bytes calldata pkscript,
        bytes calldata message,
        bytes calldata signature
    ) external returns (bool success);
}

Parameters

pkscript
bytes
required
The Bitcoin output script (pkscript) associated with the signing wallet.
message
bytes
required
The message that was signed.
signature
bytes
required
The BIP-322 signature bytes produced by the Bitcoin wallet.

Returns

success
bool
true if the signature is valid for the given pkscript and message, false otherwise.

Example usage

IBIP322_Verifier constant BIP322 = IBIP322_Verifier(address(0xFE));

function authenticateWithBitcoin(
    bytes calldata pkscript,
    bytes calldata message,
    bytes calldata signature
) external {
    bool valid = BIP322.verify(pkscript, message, signature);
    require(valid, "Invalid Bitcoin signature");
    // proceed with authorized action
}
Retrieves full details of a Bitcoin transaction by its transaction ID. Contracts can use this to confirm that specific Bitcoin transactions occurred, enabling payment-triggered logic without any off-chain oracle.Use case: Trustless Bitcoin payment verification — contracts can confirm that specific Bitcoin transactions occurred, enabling payment-triggered logic.
// Precompile address: 0xFD

/**
 * @dev Get Bitcoin transaction details using tx ids.
 */
interface IBTC_Transaction {
    function getTxDetails(
        bytes32 txid
    )
        external
        view
        returns (
            uint256 block_height,
            bytes32[] memory vin_txids,
            uint256[] memory vin_vouts,
            bytes[] memory vin_scriptPubKeys,
            uint256[] memory vin_values,
            bytes[] memory vout_scriptPubKeys,
            uint256[] memory vout_values
        );
}

Parameters

txid
bytes32
required
The Bitcoin transaction ID to look up.

Returns

block_height
uint256
The Bitcoin block height at which this transaction was confirmed.
vin_txids
bytes32[]
Transaction IDs of all inputs.
vin_vouts
uint256[]
Output indices of all inputs (corresponding to vin_txids).
vin_scriptPubKeys
bytes[]
The scriptPubKey of each input’s source output.
vin_values
uint256[]
The value in satoshis of each input.
vout_scriptPubKeys
bytes[]
The scriptPubKey of each output.
vout_values
uint256[]
The value in satoshis of each output.

Example usage

IBTC_Transaction constant BTC_TX = IBTC_Transaction(address(0xFD));

function verifyPayment(bytes32 txid, bytes memory expectedScript, uint256 expectedSats) external view returns (bool) {
    (
        ,
        ,
        ,
        ,
        ,
        bytes[] memory vout_scriptPubKeys,
        uint256[] memory vout_values
    ) = BTC_TX.getTxDetails(txid);

    for (uint i = 0; i < vout_scriptPubKeys.length; i++) {
        if (
            keccak256(vout_scriptPubKeys[i]) == keccak256(expectedScript) &&
            vout_values[i] >= expectedSats
        ) {
            return true;
        }
    }
    return false;
}
Tracks the current location of an individual satoshi given its prior location in a specific transaction output. This enables on-chain logic that follows ordinal satoshi provenance.
// Precompile address: 0xFC

/**
 * @dev Get last satoshi location of a given sat location in a transaction.
 */
interface IBTC_LastSatLoc {
    function getLastSatLocation(
        bytes32 txid,
        uint256 vout,
        uint256 sat
    ) external view returns (
        bytes32 last_txid,
        uint256 last_vout,
        uint256 last_sat,
        bytes memory old_pkscript,
        bytes memory new_pkscript
    );
}

Parameters

txid
bytes32
required
The transaction ID where the satoshi was last known to reside.
vout
uint256
required
The output index within that transaction.
sat
uint256
required
The ordinal offset of the specific satoshi within the output.

Returns

last_txid
bytes32
The transaction ID of the satoshi’s most recent move.
last_vout
uint256
The output index in the most recent transaction.
last_sat
uint256
The ordinal offset in the most recent output.
old_pkscript
bytes
The pkscript of the previous owner.
new_pkscript
bytes
The pkscript of the current owner.
Checks whether a BRC-20 token holder has locked their inscriptions to a specific Bitcoin script for at least a given number of blocks. This enables on-chain staking and governance systems where users lock ordinals on Bitcoin to prove commitment.Use case: Staking and governance — users lock ordinals on Bitcoin to prove commitment; contracts verify the lock status and grant voting rights or rewards.
// Precompile address: 0xFB

/**
 * @dev Get locked pkscript of a given Bitcoin wallet script.
 */
interface IBTC_LockedPkscript {
    function getLockedPkscript(
        bytes calldata pkscript,
        uint256 lock_block_count
    ) external view returns (bytes memory locked_pkscript);
}

Parameters

pkscript
bytes
required
The Bitcoin wallet script (pkscript) of the token holder to check.
lock_block_count
uint256
required
The minimum number of blocks the inscriptions must be locked.

Returns

locked_pkscript
bytes
The locked pkscript if the holder has an active lock meeting the block count requirement, otherwise empty bytes.

Example usage

IBTC_LockedPkscript constant LOCK = IBTC_LockedPkscript(address(0xFB));

function checkStakeStatus(bytes calldata userPkscript) external view returns (bool isStaked) {
    bytes memory locked = LOCK.getLockedPkscript(userPkscript, 144); // ~1 day
    return locked.length > 0;
}
Returns the Bitcoin transaction ID of the transaction that sent the current BRC2.0 inscription to OP_RETURN, thereby activating it. This allows contracts to bind their state or events to a specific Bitcoin transaction.Use cases: Binding contract state or events to a specific Bitcoin transaction, deterministic linkage between on-chain BTC activity and EVM-level logic, implementing receipt-style verification, replay protection, and audit trails.
// Precompile address: 0xFA

interface TxIdPrecompile {
    function getBtcTxId() external view returns (bytes32);
}

Returns

(return value)
bytes32
The Bitcoin transaction ID (txid) of the transaction that activated the current BRC2.0 inscription.

Example usage

TxIdPrecompile constant TX_ID = TxIdPrecompile(address(0xFA));

mapping(bytes32 => bool) public processedTxs;

function processWithReplayProtection() external {
    bytes32 btcTxId = TX_ID.getBtcTxId();
    require(!processedTxs[btcTxId], "Already processed");
    processedTxs[btcTxId] = true;
    // perform action
}