@btc-vision/btc-runtime 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -10,22 +10,23 @@
10
10
 
11
11
  ## 2. Grant of License
12
12
 
13
- This License permits User to view the Software via the repository hosting the Software ("Hosting Service"). Except as
14
- provided in this Section, no other use of the Software is permitted. The User may not modify, copy, reproduce,
15
- republish, upload, post, transmit, or distribute the Software in any way.
13
+ This License permits User to view the Software via the repository hosting the
14
+ Software ("Hosting Service"). Except as provided in this Section, no other use
15
+ of the Software is permitted. The User may not copy, republish, or distribute the Software in any way.
16
16
 
17
17
  ## 3. Restrictions
18
18
 
19
- - **Modification and Distribution**: User is prohibited from modifying, merging, distributing, sublicensing, and/or
20
- selling copies of the Software.
21
19
  - **Commercial Use**: User is prohibited from using the Software for any commercial purposes.
22
- - **Reverse Engineering**: User is prohibited from reverse engineering, decompiling, or disassembling the Software.
20
+ - **Claim of Ownership**: User acknowledges that the Software is the property of the Licensor and that they do not have
21
+ any ownership rights to the Software.
23
22
 
24
23
  ## 4. Termination
25
24
 
26
25
  This License is effective until terminated by the Licensor. It will terminate immediately without notice from the
27
26
  Licensor if User fails to comply with any provision of this License. Upon termination, User must destroy all copies of
28
- the Software.
27
+ the Software. This License will also terminate if the User attempts to circumvent the restrictions set forth in Section
28
+
29
+ 3.
29
30
 
30
31
  ## 5. Copyright Notice
31
32
 
package/README.md CHANGED
@@ -9,12 +9,37 @@
9
9
 
10
10
  [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
11
11
 
12
+ ## Table of Contents
13
+
14
+ 1. [Introduction](#introduction)
15
+ 2. [Installation](#installation)
16
+ 3. [Core Concepts](#core-concepts)
17
+ - [Blockchain Environment](#blockchain-environment)
18
+ - [Contracts](#contracts)
19
+ - [Events](#events)
20
+ - [Pointers and Storage Management](#pointers-and-storage-management)
21
+ 4. [Usage Examples](#usage-examples)
22
+ 5. [Advanced Topics](#advanced-topics)
23
+ 6. [Additional Documentation](#additional-documentation)
24
+ 7. [License](#license)
25
+
12
26
  ## Introduction
13
27
 
14
- The OPNet Smart Contract Runtime contains all the necessary components to effectively create smart contracts on Bitcoin
15
- L1. The runtime is written in AssemblyScript.
28
+ The OPNet Smart Contract Runtime provides the foundational components required for creating smart contracts on Bitcoin
29
+ Layer 1 (L1). Written in AssemblyScript, this runtime allows developers to leverage WebAssembly for efficient contract
30
+ execution while integrating deeply with Bitcoin's decentralized architecture.
31
+
32
+ ### Features
16
33
 
17
- ### Installation
34
+ - **AssemblyScript and WebAssembly:** Efficient and high-performance contract execution using WebAssembly.
35
+ - **Bitcoin Integration:** Direct interaction with Bitcoin L1, enabling the creation of decentralized applications that
36
+ operate on the Bitcoin network.
37
+ - **Comprehensive Storage Management:** Flexible and secure storage management using primary pointers and sub-pointers,
38
+ ensuring data integrity through cryptographic proofs.
39
+ - **Event Handling:** Sophisticated event system for contract state changes, allowing easy tracking and logging of
40
+ contract activities.
41
+
42
+ ## Installation
18
43
 
19
44
  1. Clone the repository:
20
45
  ```bash
@@ -26,9 +51,136 @@ L1. The runtime is written in AssemblyScript.
26
51
  ```
27
52
  3. Install the necessary dependencies:
28
53
  ```bash
29
- npm i
54
+ npm install
30
55
  ```
31
56
 
57
+ ## Core Concepts
58
+
59
+ ### Blockchain Environment
60
+
61
+ The `Blockchain` object environment is the backbone of the OPNet runtime, providing essential functionality for
62
+ interacting with the blockchain, such as managing contract states, handling transactions, and emitting events.
63
+
64
+ For more detailed information, see the [Blockchain.md](docs/Blockchain.md) documentation.
65
+
66
+ ### Contracts
67
+
68
+ Contracts in OPNet are AssemblyScript classes that extend the `OP_NET` base class. The constructor pattern differs from
69
+ Solidity's, as it runs every time a contract is instantiated, so developers should not use the constructor for
70
+ persistent initialization.
71
+
72
+ For a detailed guide on how to structure contracts, refer to the [Contract.md](docs/Contract.md) documentation.
73
+
74
+ ### Events
75
+
76
+ Events in OPNet allow contracts to emit signals that external observers can listen to. They are crucial for tracking
77
+ state changes and interactions within the contract.
78
+
79
+ For a comprehensive explanation on how to define and use events, refer to the [Events.md](docs/Events.md) documentation.
80
+
81
+ ### Pointers and Storage Management
82
+
83
+ Storage in OPNet is managed using a combination of pointers (`u16`) and sub-pointers (`u256`). These are encoded and
84
+ hashed to generate unique storage locations that are secure and verifiable. This approach ensures that the data stored
85
+ is tamper-proof and can be efficiently accessed.
86
+
87
+ For more details on pointers and storage management, see the [Pointers.md](docs/Pointers.md)
88
+ and [Storage.md](docs/Storage.md) documentation.
89
+
90
+ ## Usage Examples
91
+
92
+ ### Creating a Basic Token Contract
93
+
94
+ Here is a real-world example of how to create a basic token contract using the OPNet Smart Contract Runtime. This
95
+ contract follows the OP20 standard.
96
+
97
+ ```typescript
98
+ import { u128, u256 } from 'as-bignum/assembly';
99
+ import {
100
+ Address, Blockchain,
101
+ BytesWriter,
102
+ Calldata,
103
+ encodeSelector,
104
+ Map,
105
+ OP20InitParameters,
106
+ Selector,
107
+ } from '@btc-vision/btc-runtime/runtime';
108
+ import { DeployableOP_20 } from '@btc-vision/btc-runtime/runtime/contracts/DeployableOP_20';
109
+
110
+ @final
111
+ export class MyToken extends DeployableOP_20 {
112
+ constructor() {
113
+ super();
114
+
115
+ // DO NOT USE TO DEFINE VARIABLE THAT ARE NOT CONSTANT. SEE "solidityLikeConstructor" BELOW.
116
+ }
117
+
118
+ // "solidityLikeConstructor" This is a solidity-like constructor. This method will only run once.
119
+ public onInstantiated(): void {
120
+ if (!this.isInstantiated) {
121
+ super.onInstantiated(); // IMPORTANT.
122
+
123
+ const maxSupply: u256 = u128.fromString('100000000000000000000000000').toU256(); // Your max supply.
124
+ const decimals: u8 = 18; // Your decimals.
125
+ const name: string = 'MyToken'; // Your token name.
126
+ const symbol: string = 'TOKEN'; // Your token symbol.
127
+
128
+ this.instantiate(new OP20InitParameters(maxSupply, decimals, name, symbol));
129
+
130
+ // Add your logic here. Eg, minting the initial supply:
131
+ // this._mint(Blockchain.origin, maxSupply);
132
+ }
133
+ }
134
+
135
+ public override callMethod(method: Selector, calldata: Calldata): BytesWriter {
136
+ switch (method) {
137
+ default:
138
+ return super.callMethod(method, calldata);
139
+ }
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### Emitting Events
145
+
146
+ ```typescript
147
+ class MyContract extends OP_NET {
148
+ public someAction(): void {
149
+ const event = new CustomEvent(Blockchain.sender, u256.fromU32(100));
150
+ this.emitEvent(event);
151
+ }
152
+ }
153
+ ```
154
+
155
+ ## Advanced Topics
156
+
157
+ ### Storage Management with Cryptographic Proofs
158
+
159
+ Storage pointers and sub-pointers are encoded and hashed to create unique and secure storage locations. These storage
160
+ locations are managed using the `Blockchain` class's `setStorageAt` and `getStorageAt` methods, ensuring data integrity
161
+ and preventing tampering.
162
+
163
+ ### Using Serializable Data Structures
164
+
165
+ For complex data types, the `Serializable` class allows you to manage and persist data structures across multiple
166
+ storage slots.
167
+
168
+ ```typescript
169
+ class ComplexData extends Serializable {
170
+ // Implementation
171
+ }
172
+ ```
173
+
174
+ ## Additional Documentation
175
+
176
+ For more detailed explanations on specific topics, refer to the individual documentation files:
177
+
178
+ - [Blockchain.md](docs/Blockchain.md)
179
+ - [Contract.md](docs/Contract.md)
180
+ - [Events.md](docs/Events.md)
181
+ - [Pointers.md](docs/Pointers.md)
182
+ - [Storage.md](docs/Storage.md)
183
+
32
184
  ## License
33
185
 
34
- View the license by clicking [here](https://github.com/btc-vision/wbtc/blob/main/LICENSE.md).
186
+ This project is licensed under the MIT License. View the full license [here](LICENSE.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "types": "btc/index.ts",
@@ -33,7 +33,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
33
33
  protected readonly _name: StoredString;
34
34
  protected readonly _symbol: StoredString;
35
35
 
36
- protected constructor(params?: OP20InitParameters) {
36
+ protected constructor(params: OP20InitParameters | null = null) {
37
37
  super();
38
38
 
39
39
  this.allowanceMap = new MultiAddressMemoryMap<Address, Address, MemorySlotData<u256>>(
@@ -90,12 +90,12 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
90
90
  }
91
91
 
92
92
  public instantiate(params: OP20InitParameters, skipOwnerVerification: boolean = false): void {
93
- if (!skipOwnerVerification) this.onlyOwner(Blockchain.origin());
94
-
95
93
  if (!this._maxSupply.value.isZero()) {
96
94
  throw new Revert('Already initialized');
97
95
  }
98
96
 
97
+ if (!skipOwnerVerification) this.onlyOwner(Blockchain.origin);
98
+
99
99
  if (params.decimals > 32) {
100
100
  throw new Revert('Decimals can not be more than 32');
101
101
  }
@@ -125,7 +125,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
125
125
  const resp = this._approve(spender, value);
126
126
  response.writeBoolean(resp);
127
127
 
128
- this.createApproveEvent(Blockchain.origin(), spender, value);
128
+ this.createApproveEvent(Blockchain.origin, spender, value);
129
129
 
130
130
  return response;
131
131
  }
@@ -234,7 +234,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
234
234
  }
235
235
 
236
236
  protected _approve(spender: Address, value: u256): boolean {
237
- const callee = Blockchain.origin();
237
+ const callee = Blockchain.origin;
238
238
 
239
239
  const senderMap = this.allowanceMap.get(callee);
240
240
  senderMap.set(spender, value);
@@ -254,8 +254,8 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
254
254
  throw new Revert(`No tokens`);
255
255
  }
256
256
 
257
- const callee = Blockchain.origin();
258
- const caller = Blockchain.sender();
257
+ const callee = Blockchain.origin;
258
+ const caller = Blockchain.sender;
259
259
 
260
260
  if (onlyOwner) this.onlyOwner(callee); // only indexers can burn tokens
261
261
 
@@ -276,7 +276,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
276
276
  }
277
277
 
278
278
  protected _mint(to: Address, value: u256, onlyOwner: boolean = true): boolean {
279
- const callee = Blockchain.origin();
279
+ const callee = Blockchain.origin;
280
280
 
281
281
  if (onlyOwner) this.onlyOwner(callee);
282
282
 
@@ -299,7 +299,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
299
299
  }
300
300
 
301
301
  protected _transfer(to: string, value: u256): boolean {
302
- const caller = Blockchain.origin();
302
+ const caller = Blockchain.origin;
303
303
 
304
304
  if (!this.balanceOfMap.has(caller)) throw new Revert();
305
305
  if (this.isSelf(caller)) throw new Revert('Can not transfer from self account');
@@ -355,8 +355,8 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
355
355
  }
356
356
 
357
357
  protected _transferFrom(from: Address, to: Address, value: u256): boolean {
358
- const spender = Blockchain.origin();
359
- if (Blockchain.sender() !== from) {
358
+ const spender = Blockchain.origin;
359
+ if (Blockchain.sender !== from) {
360
360
  throw new Revert('Not caller.');
361
361
  }
362
362
 
@@ -9,14 +9,12 @@ import { MAX_EVENT_DATA_SIZE, NetEvent } from '../events/NetEvent';
9
9
  import { StoredBoolean } from '../storage/StoredBoolean';
10
10
 
11
11
  export class OP_NET implements IBTC {
12
- private readonly instantiated: StoredBoolean = new StoredBoolean(Blockchain.nextPointer, false);
12
+ protected readonly instantiated: StoredBoolean = new StoredBoolean(
13
+ Blockchain.nextPointer,
14
+ false,
15
+ );
13
16
 
14
- constructor() {
15
- if (!this.instantiated.value) {
16
- this.instantiated.value = true;
17
- this.onContractInstantiate();
18
- }
19
- }
17
+ constructor() {}
20
18
 
21
19
  public get address(): string {
22
20
  return Blockchain.contractAddress;
@@ -26,6 +24,16 @@ export class OP_NET implements IBTC {
26
24
  return Blockchain.owner;
27
25
  }
28
26
 
27
+ public get isInstantiated(): bool {
28
+ return this.instantiated.value;
29
+ }
30
+
31
+ public onInstantiated(): void {
32
+ if (!this.isInstantiated) {
33
+ this.instantiated.value = true;
34
+ }
35
+ }
36
+
29
37
  public callMethod(method: Selector, _calldata: Calldata): BytesWriter {
30
38
  switch (method) {
31
39
  default:
@@ -33,9 +41,6 @@ export class OP_NET implements IBTC {
33
41
  }
34
42
  }
35
43
 
36
- // Overwrite this method in your contract
37
- public onContractInstantiate(): void {}
38
-
39
44
  public callView(method: Selector): BytesWriter {
40
45
  const response = new BytesWriter();
41
46
 
@@ -31,12 +31,29 @@ export class BlockchainEnvironment {
31
31
 
32
32
  private storage: PointerStorage = new MapU256();
33
33
  private events: NetEvent[] = [];
34
+ private currentBlock: u256 = u256.Zero;
35
+
36
+ constructor() {}
34
37
 
35
38
  private _origin: PotentialAddress = null;
39
+
40
+ public get origin(): Address {
41
+ if (!this._origin) {
42
+ throw this.error('Callee is required');
43
+ }
44
+
45
+ return this._origin as Address;
46
+ }
47
+
36
48
  private _sender: PotentialAddress = null;
37
- private currentBlock: u256 = u256.Zero;
38
49
 
39
- constructor() {}
50
+ public get sender(): Address {
51
+ if (!this._sender) {
52
+ throw this.error('Caller is required');
53
+ }
54
+
55
+ return this._sender as Address;
56
+ }
40
57
 
41
58
  private _timestamp: u64 = 0;
42
59
 
@@ -98,22 +115,6 @@ export class BlockchainEnvironment {
98
115
  return this.currentBlock.toU64();
99
116
  }
100
117
 
101
- public origin(): Address {
102
- if (!this._origin) {
103
- throw this.error('Callee is required');
104
- }
105
-
106
- return this._origin as Address;
107
- }
108
-
109
- public sender(): Address {
110
- if (!this._sender) {
111
- throw this.error('Caller is required');
112
- }
113
-
114
- return this._sender as Address;
115
- }
116
-
117
118
  public setEnvironment(data: Uint8Array): void {
118
119
  const reader: BytesReader = new BytesReader(data);
119
120
 
@@ -22,7 +22,9 @@ export class StoredU256 {
22
22
 
23
23
  @inline
24
24
  public set value(value: u256) {
25
- if (u256.eq(value, this._value)) return;
25
+ if (u256.eq(value, this._value)) {
26
+ return;
27
+ }
26
28
 
27
29
  this._value = value;
28
30