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.
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.
| 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 |
npm install @btc-vision/btc-runtimeHere'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);
}
}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 |
Comprehensive documentation is available in the docs/ directory:
- Installation - Setup and configuration
- First Contract - Step-by-step tutorial
- Project Structure - Directory layout
- Blockchain Environment - Runtime context
- Storage System - How data persistence works
- Pointers - Storage key management
- Events - State change notifications
- Security - Protection mechanisms
- OP_NET Base - Abstract contract class
- OP20 Token - Fungible token standard
- OP20S Signatures - Gasless approvals
- OP721 NFT - Non-fungible tokens
- ReentrancyGuard - Reentrancy protection
- Address - 32-byte address handling
- SafeMath - Overflow-safe arithmetic
- Calldata - Input parsing
- BytesWriter/Reader - Serialization
- Stored Primitives - Basic value storage
- Stored Arrays - Array storage
- Stored Maps - Key-value storage
- Memory Maps - In-memory mappings
- Cross-Contract Calls - Inter-contract communication
- Signature Verification - Cryptographic operations
- Quantum Resistance - ML-DSA support
- Bitcoin Scripts - Script building
- Plugins - Extending functionality
- Basic Token - Simple OP20 implementation
- NFT with Reservations - Advanced NFT
- Stablecoin - Role-based token
- Oracle Integration - Price feeds
- Blockchain - Environment methods
- OP20 - Token standard API
- OP721 - NFT standard API
- SafeMath - Math operations
- Storage - Storage classes
- Events - Event classes
# Run all tests with verbose output
npm test
# Run tests with summary only
npm run test:cibtc-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
// 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
}
}// 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
);
}// 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!// 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);Contributions are welcome! Please ensure all tests pass before submitting a pull request.
npm testThis project is licensed under the Apache-2.0 License. See LICENSE for details.
- Website: OPNet
- Documentation: docs/
- Security: SECURITY.md
- GitHub: btc-vision/btc-runtime
- Issues: GitHub Issues
- Auditor: Verichains