Skip to content

btc-vision/btc-runtime

Repository files navigation

OPNet Smart Contract Runtime

Bitcoin AssemblyScript TypeScript NodeJS WebAssembly NPM

code style: prettier

Overview

The OPNet Smart Contract Runtime is the foundational framework for building decentralized applications directly on Bitcoin Layer 1 (L1). Written in AssemblyScript and compiled to WebAssembly, btc-runtime enables developers to create, deploy, and execute smart contracts on the Bitcoin network with the same expressiveness as Ethereum's Solidity.

Unlike Bitcoin Layer 2 solutions, OPNet operates directly on Bitcoin's base layer, inheriting Bitcoin's security guarantees and decentralization properties while adding programmable smart contract capabilities.

What is OPNet?

OPNet (Open Protocol Network) is a consensus-layer built on Bitcoin L1. It allows developers to write smart contracts in AssemblyScript or similar that compile to WebAssembly (WASM) and execute deterministically across all network nodes. Think of it as "Solidity for Bitcoin" - you get the programmability of Ethereum with the security of Bitcoin.

Why AssemblyScript?

AssemblyScript compiles to WebAssembly, which provides:

  • Deterministic execution across all platforms and nodes
  • Near-native performance for compute-intensive operations
  • Memory safety through WASM's sandboxed environment
  • Familiar syntax for TypeScript/JavaScript developers

IMPORTANT: Floating-Point Arithmetic is Prohibited

Floating-point arithmetic (f32, f64) is strictly prohibited in blockchain and smart contract environments. Floating-point operations are non-deterministic across different CPU architectures, compilers, and platforms due to differences in rounding, precision, and IEEE 754 implementation details.

Always use integer arithmetic (u128, u256) for all blockchain computations. For decimal values, use fixed-point representation (e.g., store currency as smallest units like satoshis). This library provides full support for 128-bit and 256-bit integer operations through @btc-vision/as-bignum.

Security Audit

Verichains

Audited by Verichains Security Report

This runtime has been professionally audited by Verichains, a leading blockchain security firm. The audit covered all core components including contract standards (OP20, OP721), storage systems, cryptographic operations, and security mechanisms.

For full details, see SECURITY.md.

Features

Feature Description
Contract Standards OP20 (fungible tokens), OP721 (NFTs), OP20S (gasless signatures)
Storage System Pointer-based persistent storage with SHA256 key hashing
SafeMath Overflow/underflow protection for all arithmetic operations
Reentrancy Protection Built-in guards with STANDARD and CALLBACK modes
Cryptographic Operations Schnorr signatures, ML-DSA (quantum-resistant), SHA256
Bitcoin Integration Transaction parsing, address validation, script building
Event System 352-byte events for state change notifications
Cross-Contract Calls Inter-contract communication with configurable failure handling

Installation

npm install @btc-vision/btc-runtime

Quick Start

Your First Contract

Here's a minimal OP20 token contract to get you started:

import { u256 } from '@btc-vision/as-bignum/assembly';
import {
    Blockchain,
    BytesWriter,
    Calldata,
    OP20,
    OP20InitParameters,
} from '@btc-vision/btc-runtime/runtime';

@final
export class MyToken extends OP20 {
    public constructor() {
        super();
        // NOTE: Constructor runs on EVERY interaction, not just deployment!
    }

    // This runs ONCE when the contract is deployed (like Solidity's constructor)
    public override onDeployment(_calldata: Calldata): void {
        const maxSupply: u256 = u256.fromString('1000000000000000000000000'); // 1 million tokens
        const decimals: u8 = 18;
        const name: string = 'MyToken';
        const symbol: string = 'MTK';

        this.instantiate(new OP20InitParameters(maxSupply, decimals, name, symbol));

        // Mint initial supply to deployer
        this._mint(Blockchain.tx.origin, maxSupply);
    }

    // Custom mint function (deployer only)
    public mint(calldata: Calldata): BytesWriter {
        this.onlyDeployer(Blockchain.tx.sender);

        const to = calldata.readAddress();
        const amount = calldata.readU256();
        this._mint(to, amount);

        return new BytesWriter(0);
    }
}

Solidity Comparison

If you're coming from Solidity/EVM development, here's how OPNet concepts map:

Solidity/EVM OPNet/btc-runtime Notes
contract MyContract class MyContract extends OP_NET Base class inheritance
constructor() onDeployment(calldata) Runs once at deployment
msg.sender Blockchain.tx.sender Immediate caller
tx.origin Blockchain.tx.origin Original transaction signer
block.number Blockchain.block.number Current block height
mapping(address => uint) AddressMemoryMap + StoredU256 Pointer-based storage
emit Transfer(...) this.emitEvent(new TransferEvent(...)) Event emission
ERC20 OP20 Fungible token standard
ERC721 OP721 Non-fungible token standard
uint256 u256 256-bit unsigned integer
require(condition, "msg") if (!condition) throw new Revert("msg") Error handling
modifier onlyOwner this.onlyDeployer(sender) Access control

Documentation

Comprehensive documentation is available in the docs/ directory:

Getting Started

Core Concepts

Contract Standards

Types & Utilities

Storage Types

Advanced Topics

Examples

API Reference

Running Tests

# Run all tests with verbose output
npm test

# Run tests with summary only
npm run test:ci

Project Structure

btc-runtime/
├── runtime/                    # Core runtime library
│   ├── contracts/              # Contract base classes (OP_NET, OP20, OP721)
│   ├── storage/                # Storage types (Stored*, Maps)
│   ├── math/                   # SafeMath operations
│   ├── types/                  # Core types (Address, Calldata)
│   ├── events/                 # Event system
│   └── env/                    # Blockchain environment
├── docs/                       # Documentation
└── tests/                      # Test suite

Key Differences from Solidity

1. Constructor Behavior

// OPNet: Constructor runs EVERY time
export class MyContract extends OP_NET {
    constructor() {
        super();
        // DON'T put initialization here - it runs on every call!
    }

    // Use this for one-time initialization (like Solidity constructor)
    public override onDeployment(calldata: Calldata): void {
        // Initialize storage here
    }
}

2. Storage is Explicit

// Solidity: Implicit storage
// mapping(address => uint256) balances;

// OPNet: Explicit pointer allocation
class Test {
    private balancePointer: u16 = Blockchain.nextPointer;
    private balances: AddressMemoryMap<Address, StoredU256> = new AddressMemoryMap(
        this.balancePointer,
        u256.Zero
    );
}

3. Integer Types

// OPNet uses u256 from as-bignum (NOT native BigInt)
import { u256 } from '@btc-vision/as-bignum/assembly';

const a = u256.from(100);
const b = u256.from(50);
const sum = SafeMath.add(a, b);  // Always use SafeMath!

4. No Floating Point

// WRONG - Non-deterministic!
// const price: f64 = 1.5;

// CORRECT - Fixed-point with integers
const PRECISION: u256 = u256.fromU64(1_000_000); // 6 decimals
const price: u256 = SafeMath.mul(amount, PRECISION);

Contributing

Contributions are welcome! Please ensure all tests pass before submitting a pull request.

npm test

License

This project is licensed under the Apache-2.0 License. See LICENSE for details.

Links

About

Assemblyscript btc runtime

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 10