@btc-vision/btc-runtime 1.0.0

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.
Files changed (41) hide show
  1. package/LICENSE.md +62 -0
  2. package/README.md +34 -0
  3. package/package.json +46 -0
  4. package/runtime/buffer/BytesReader.ts +193 -0
  5. package/runtime/buffer/BytesWriter.ts +322 -0
  6. package/runtime/contracts/OP_20.ts +377 -0
  7. package/runtime/contracts/OP_NET.ts +77 -0
  8. package/runtime/contracts/interfaces/IOP_20.ts +25 -0
  9. package/runtime/env/BTCEnvironment.ts +372 -0
  10. package/runtime/env/global.ts +18 -0
  11. package/runtime/env/index.ts +3 -0
  12. package/runtime/events/NetEvent.ts +27 -0
  13. package/runtime/events/predefined/ApproveEvent.ts +16 -0
  14. package/runtime/events/predefined/BurnEvent.ts +13 -0
  15. package/runtime/events/predefined/ClaimEvent.ts +13 -0
  16. package/runtime/events/predefined/MintEvent.ts +15 -0
  17. package/runtime/events/predefined/StakeEvent.ts +13 -0
  18. package/runtime/events/predefined/TransferEvent.ts +16 -0
  19. package/runtime/events/predefined/UnstakeEvent.ts +13 -0
  20. package/runtime/events/predefined/index.ts +7 -0
  21. package/runtime/exports/index.ts +57 -0
  22. package/runtime/generic/Map.ts +55 -0
  23. package/runtime/index.ts +45 -0
  24. package/runtime/interfaces/IBTC.ts +6 -0
  25. package/runtime/lang/Definitions.ts +1 -0
  26. package/runtime/math/abi.ts +37 -0
  27. package/runtime/math/bytes.ts +34 -0
  28. package/runtime/math/cyrb53.ts +46 -0
  29. package/runtime/math/rnd.ts +51 -0
  30. package/runtime/math/sha256.ts +270 -0
  31. package/runtime/memory/AddressMemoryMap.ts +64 -0
  32. package/runtime/memory/KeyMerger.ts +72 -0
  33. package/runtime/memory/MemorySlot.ts +1 -0
  34. package/runtime/memory/MemorySlotPointer.ts +3 -0
  35. package/runtime/memory/MultiAddressMemoryMap.ts +76 -0
  36. package/runtime/storage/StoredU256.ts +320 -0
  37. package/runtime/types/Address.ts +5 -0
  38. package/runtime/types/Revert.ts +5 -0
  39. package/runtime/types/SafeMath.ts +137 -0
  40. package/runtime/types/index.ts +8 -0
  41. package/runtime/universal/ABIRegistry.ts +72 -0
@@ -0,0 +1,76 @@
1
+ import { Address } from '../types/Address';
2
+ import { MemorySlotData } from './MemorySlot';
3
+ import { u256 } from 'as-bignum/assembly';
4
+ import { KeyMerger } from './KeyMerger';
5
+ import { Map } from '../generic/Map';
6
+
7
+ @final
8
+ export class MultiAddressMemoryMap<
9
+ K extends string,
10
+ K2 extends string,
11
+ V extends MemorySlotData<u256>,
12
+ > extends Map<K, KeyMerger<K, K2, V>> {
13
+ public pointer: u16;
14
+
15
+ private readonly memoryAllocatorAddress: Address;
16
+
17
+ constructor(
18
+ pointer: u16,
19
+ self: Address,
20
+ private readonly defaultValue: V,
21
+ ) {
22
+ super();
23
+
24
+ this.pointer = pointer;
25
+ this.memoryAllocatorAddress = self;
26
+ }
27
+
28
+ public get(key: K): KeyMerger<K, K2, V> {
29
+ this.createKeyMerger(key);
30
+
31
+ return super.get(key);
32
+ }
33
+
34
+ public setUpperKey(key: K, key2: K2, value: V): this {
35
+ this.createKeyMerger(key);
36
+
37
+ const subMap = super.get(key);
38
+ if (subMap) {
39
+ subMap.set(key2, value);
40
+ }
41
+
42
+ return this;
43
+ }
44
+
45
+ public set(key: K, value: KeyMerger<K, K2, V>): this {
46
+ this.createKeyMerger(key);
47
+
48
+ return <this>(<unknown>super.set(key, value));
49
+ }
50
+
51
+ public has(key: K): bool {
52
+ return super.has(key);
53
+ }
54
+
55
+ public delete(key: K): bool {
56
+ return super.delete(key);
57
+ }
58
+
59
+ public clear(): void {
60
+ super.clear();
61
+ }
62
+
63
+ private createKeyMerger(key: K): void {
64
+ if (!super.has(key)) {
65
+ super.set(
66
+ key,
67
+ new KeyMerger<K, K2, V>(
68
+ key,
69
+ this.pointer,
70
+ this.memoryAllocatorAddress,
71
+ this.defaultValue,
72
+ ),
73
+ );
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,320 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { SafeMath } from '../types/SafeMath';
3
+ import { Address } from '../types/Address';
4
+ import { MemorySlotPointer } from '../memory/MemorySlotPointer';
5
+ import { Blockchain } from '../env';
6
+
7
+ @final
8
+ export class StoredU256 {
9
+ constructor(
10
+ public address: Address,
11
+ public pointer: u16,
12
+ public subPointer: MemorySlotPointer,
13
+ private defaultValue: u256,
14
+ ) {
15
+ this._value = Blockchain.getStorageAt(
16
+ this.address,
17
+ this.pointer,
18
+ this.subPointer,
19
+ this.defaultValue,
20
+ );
21
+ }
22
+
23
+ private _value: u256 = u256.Zero;
24
+
25
+ @inline
26
+ public get value(): u256 {
27
+ this.ensureValue();
28
+
29
+ return this._value;
30
+ }
31
+
32
+ @inline
33
+ @operator('+')
34
+ public add(value: u256): this {
35
+ this.ensureValue();
36
+
37
+ this._value = SafeMath.add(this._value, value);
38
+ Blockchain.setStorageAt(
39
+ this.address,
40
+ this.pointer,
41
+ this.subPointer,
42
+ this._value,
43
+ this.defaultValue,
44
+ );
45
+
46
+ return this;
47
+ }
48
+
49
+ @inline
50
+ @operator('-')
51
+ public sub(value: u256): this {
52
+ this.ensureValue();
53
+
54
+ this._value = SafeMath.sub(this._value, value);
55
+ Blockchain.setStorageAt(
56
+ this.address,
57
+ this.pointer,
58
+ this.subPointer,
59
+ this._value,
60
+ this.defaultValue,
61
+ );
62
+
63
+ return this;
64
+ }
65
+
66
+ @inline
67
+ @operator('*')
68
+ public mul(value: u256): this {
69
+ this.ensureValue();
70
+
71
+ this._value = SafeMath.mul(this._value, value);
72
+ Blockchain.setStorageAt(
73
+ this.address,
74
+ this.pointer,
75
+ this.subPointer,
76
+ this._value,
77
+ this.defaultValue,
78
+ );
79
+
80
+ return this;
81
+ }
82
+
83
+ @inline
84
+ @operator('==')
85
+ public eq(value: u256): boolean {
86
+ this.ensureValue();
87
+
88
+ return this._value === value;
89
+ }
90
+
91
+ @inline
92
+ @operator('!=')
93
+ public ne(value: u256): boolean {
94
+ this.ensureValue();
95
+
96
+ return this._value !== value;
97
+ }
98
+
99
+ @inline
100
+ @operator('<')
101
+ public lt(value: u256): boolean {
102
+ this.ensureValue();
103
+
104
+ return this._value < value;
105
+ }
106
+
107
+ @inline
108
+ @operator('>')
109
+ public gt(value: u256): boolean {
110
+ this.ensureValue();
111
+
112
+ return this._value > value;
113
+ }
114
+
115
+ @inline
116
+ @operator('<=')
117
+ public le(value: u256): boolean {
118
+ this.ensureValue();
119
+
120
+ return this._value <= value;
121
+ }
122
+
123
+ @inline
124
+ @operator('>=')
125
+ public ge(value: u256): boolean {
126
+ this.ensureValue();
127
+
128
+ return this._value >= value;
129
+ }
130
+
131
+ @inline
132
+ @operator('>>')
133
+ public shr(value: i32): this {
134
+ this.ensureValue();
135
+
136
+ this._value = u256.shr(this._value, value);
137
+ Blockchain.setStorageAt(
138
+ this.address,
139
+ this.pointer,
140
+ this.subPointer,
141
+ this._value,
142
+ this.defaultValue,
143
+ );
144
+
145
+ return this;
146
+ }
147
+
148
+ @inline
149
+ @operator('&')
150
+ public and(value: u256): this {
151
+ this.ensureValue();
152
+
153
+ this._value = u256.and(this._value, value);
154
+ Blockchain.setStorageAt(
155
+ this.address,
156
+ this.pointer,
157
+ this.subPointer,
158
+ this._value,
159
+ this.defaultValue,
160
+ );
161
+
162
+ return this;
163
+ }
164
+
165
+ @inline
166
+ @operator('|')
167
+ public or(value: u256): this {
168
+ this.ensureValue();
169
+
170
+ this._value = u256.or(this._value, value);
171
+ Blockchain.setStorageAt(
172
+ this.address,
173
+ this.pointer,
174
+ this.subPointer,
175
+ this._value,
176
+ this.defaultValue,
177
+ );
178
+
179
+ return this;
180
+ }
181
+
182
+ @inline
183
+ @operator('^')
184
+ public xor(value: u256): this {
185
+ this.ensureValue();
186
+
187
+ this._value = u256.xor(this._value, value);
188
+ Blockchain.setStorageAt(
189
+ this.address,
190
+ this.pointer,
191
+ this.subPointer,
192
+ this._value,
193
+ this.defaultValue,
194
+ );
195
+
196
+ return this;
197
+ }
198
+
199
+ @inline
200
+ @operator('**')
201
+ public pow(value: u256): this {
202
+ this.ensureValue();
203
+
204
+ // code pow from scratch
205
+ let result: u256 = u256.One;
206
+
207
+ while (value > u256.Zero) {
208
+ if (u256.and(value, u256.One)) {
209
+ result = SafeMath.mul(result, this._value);
210
+ }
211
+
212
+ this._value = SafeMath.mul(this._value, this._value);
213
+ value = u256.shr(value, 1);
214
+ }
215
+
216
+ Blockchain.setStorageAt(
217
+ this.address,
218
+ this.pointer,
219
+ this.subPointer,
220
+ this._value,
221
+ this.defaultValue,
222
+ );
223
+
224
+ return this;
225
+ }
226
+
227
+ @inline
228
+ @operator('%')
229
+ public mod(value: u256): this {
230
+ this.ensureValue();
231
+
232
+ // code mod from scratch
233
+ let result: u256 = u256.Zero;
234
+ let base: u256 = this._value;
235
+ let exp: u256 = value;
236
+
237
+ while (exp > u256.Zero) {
238
+ if (u256.and(exp, u256.One)) {
239
+ result = SafeMath.add(result, base);
240
+ }
241
+
242
+ base = SafeMath.add(base, base);
243
+ exp = u256.shr(exp, 1);
244
+ }
245
+
246
+ this._value = result;
247
+ Blockchain.setStorageAt(
248
+ this.address,
249
+ this.pointer,
250
+ this.subPointer,
251
+ this._value,
252
+ this.defaultValue,
253
+ );
254
+
255
+ return this;
256
+ }
257
+
258
+ @inline
259
+ @operator.postfix('++')
260
+ public inc(): this {
261
+ this.ensureValue();
262
+
263
+ this._value = SafeMath.add(this._value, u256.One);
264
+ Blockchain.setStorageAt(
265
+ this.address,
266
+ this.pointer,
267
+ this.subPointer,
268
+ this._value,
269
+ this.defaultValue,
270
+ );
271
+
272
+ return this;
273
+ }
274
+
275
+ @inline
276
+ @operator.postfix('--')
277
+ public dec(): this {
278
+ this.ensureValue();
279
+
280
+ this._value = SafeMath.sub(this._value, u256.One);
281
+ Blockchain.setStorageAt(
282
+ this.address,
283
+ this.pointer,
284
+ this.subPointer,
285
+ this._value,
286
+ this.defaultValue,
287
+ );
288
+
289
+ return this;
290
+ }
291
+
292
+ @inline
293
+ public set(value: u256): this {
294
+ this._value = value;
295
+
296
+ Blockchain.setStorageAt(
297
+ this.address,
298
+ this.pointer,
299
+ this.subPointer,
300
+ this._value,
301
+ this.defaultValue,
302
+ );
303
+
304
+ return this;
305
+ }
306
+
307
+ @inline
308
+ public toUint8Array(): Uint8Array {
309
+ return this._value.toUint8Array(true);
310
+ }
311
+
312
+ private ensureValue(): void {
313
+ this._value = Blockchain.getStorageAt(
314
+ this.address,
315
+ this.pointer,
316
+ this.subPointer,
317
+ this.defaultValue,
318
+ );
319
+ }
320
+ }
@@ -0,0 +1,5 @@
1
+ import { Potential } from '../lang/Definitions';
2
+
3
+ export const ADDRESS_BYTE_LENGTH: u8 = 64;
4
+ export declare type Address = string;
5
+ export declare type PotentialAddress = Potential<Address>;
@@ -0,0 +1,5 @@
1
+ export class Revert extends Error {
2
+ constructor(msg: string = '') {
3
+ super(`Execution reverted ${msg}`);
4
+ }
5
+ }
@@ -0,0 +1,137 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+
3
+ export class SafeMath {
4
+ public static ZERO: u256 = u256.fromU32(0);
5
+
6
+ public static add(a: u256, b: u256): u256 {
7
+ const c: u256 = u256.add(a, b);
8
+ if (c < a) {
9
+ throw new Error('SafeMath: addition overflow');
10
+ }
11
+ return c;
12
+ }
13
+
14
+ public static sub(a: u256, b: u256): u256 {
15
+ if (a < b) {
16
+ throw new Error('SafeMath: subtraction overflow');
17
+ }
18
+
19
+ return u256.sub(a, b);
20
+ }
21
+
22
+ public static mul(a: u256, b: u256): u256 {
23
+ if (a === SafeMath.ZERO || b === SafeMath.ZERO) {
24
+ return SafeMath.ZERO;
25
+ }
26
+
27
+ const c: u256 = u256.mul(a, b);
28
+ const d: u256 = SafeMath.div(c, a);
29
+
30
+ if (u256.ne(d, b)) {
31
+ throw new Error('SafeMath: multiplication overflow');
32
+ }
33
+
34
+ return c;
35
+ }
36
+
37
+ @inline
38
+ @unsafe
39
+ @operator('/')
40
+ static div(a: u256, b: u256): u256 {
41
+ if (b.isZero()) {
42
+ throw new Error('Division by zero');
43
+ }
44
+
45
+ if (a.isZero()) {
46
+ return new u256();
47
+ }
48
+
49
+ if (u256.lt(a, b)) {
50
+ return new u256(); // Return 0 if a < b
51
+ }
52
+
53
+ if (u256.eq(a, b)) {
54
+ return new u256(1); // Return 1 if a == b
55
+ }
56
+
57
+ let n = a.clone();
58
+ let d = b.clone();
59
+ let result = new u256();
60
+
61
+ let shift = u256.clz(d) - u256.clz(n);
62
+ d = SafeMath.shl(d, shift); // align d with n by shifting left
63
+
64
+ for (let i = shift; i >= 0; i--) {
65
+ if (u256.ge(n, d)) {
66
+ n = u256.sub(n, d);
67
+ result = u256.or(result, SafeMath.shl(new u256(1), i));
68
+ }
69
+ d = u256.shr(d, 1); // restore d to original by shifting right
70
+ }
71
+
72
+ return result;
73
+ }
74
+
75
+ @inline
76
+ @unsafe
77
+ static shl(value: u256, shift: i32): u256 {
78
+ if (shift == 0) {
79
+ return value.clone();
80
+ }
81
+
82
+ let totalBits = 256;
83
+ let bitsPerSegment = 64;
84
+
85
+ // Normalize shift to be within 0-255 range
86
+ shift &= 255;
87
+
88
+ if (shift >= totalBits) {
89
+ return new u256(); // Shift size larger than width results in zero
90
+ }
91
+
92
+ // Determine how many full 64-bit segments we are shifting
93
+ let segmentShift = (shift / bitsPerSegment) | 0;
94
+ let bitShift = shift % bitsPerSegment;
95
+
96
+ let segments = [value.lo1, value.lo2, value.hi1, value.hi2];
97
+
98
+ let result = new Array<u64>(4).fill(0);
99
+
100
+ for (let i = 0; i < segments.length; i++) {
101
+ if (i + segmentShift < segments.length) {
102
+ result[i + segmentShift] |= segments[i] << bitShift;
103
+ }
104
+ if (bitShift != 0 && i + segmentShift + 1 < segments.length) {
105
+ result[i + segmentShift + 1] |= segments[i] >>> (bitsPerSegment - bitShift);
106
+ }
107
+ }
108
+
109
+ return new u256(result[0], result[1], result[2], result[3]);
110
+ }
111
+
112
+ public static and(a: u256, b: u256): u256 {
113
+ return u256.and(a, b);
114
+ }
115
+
116
+ public static or(a: u256, b: u256): u256 {
117
+ return u256.or(a, b);
118
+ }
119
+
120
+ public static xor(a: u256, b: u256): u256 {
121
+ return u256.xor(a, b);
122
+ }
123
+
124
+ public static shr(a: u256, b: u32): u256 {
125
+ return u256.shr(a, b);
126
+ }
127
+
128
+ /**
129
+ * Increment a u256 value by 1
130
+ * @param value The value to increment
131
+ * @returns The incremented value
132
+ */
133
+ @inline
134
+ static inc(value: u256): u256 {
135
+ return value.preInc();
136
+ }
137
+ }
@@ -0,0 +1,8 @@
1
+ import { Map } from '../generic/Map';
2
+ import { MemorySlotPointer } from '../memory/MemorySlotPointer';
3
+ import { MemorySlotData } from '../memory/MemorySlot';
4
+ import { u256 } from 'as-bignum/assembly';
5
+ import { Address } from './Address';
6
+
7
+ export type PointerStorage = Map<MemorySlotPointer, MemorySlotData<u256>>;
8
+ export type BlockchainStorage = Map<Address, PointerStorage>;
@@ -0,0 +1,72 @@
1
+ import { encodeSelector, Selector } from '../math/abi';
2
+ import { BytesReader } from '../buffer/BytesReader';
3
+ import { BytesWriter } from '../buffer/BytesWriter';
4
+ import { Map } from '../generic/Map';
5
+
6
+ export type Calldata = NonNullable<BytesReader>;
7
+ export type SelectorsMap = Map<u32, Uint8Array>;
8
+
9
+ class ABIRegistryBase {
10
+ private methodMap: Selector[] = [];
11
+ private selectors: SelectorsMap = new Map();
12
+
13
+ private viewSelectors: Selector[] = [];
14
+ private allowedWriteMethods: Selector[] = [];
15
+
16
+ // Register properties with their selectors and handlers
17
+ public defineGetterSelector(name: string, canWrite: boolean): void {
18
+ const selector: Selector = encodeSelector(name);
19
+
20
+ const selectorWriter: BytesWriter = new BytesWriter();
21
+ selectorWriter.writeABISelector(name, selector);
22
+
23
+ if (!this.selectors.has(selector)) {
24
+ this.selectors.set(selector, selectorWriter.getBuffer());
25
+ }
26
+
27
+ if (canWrite) this.addToWriteMethods(selector);
28
+
29
+ if (!this.viewSelectors.includes(selector)) {
30
+ this.viewSelectors.push(selector);
31
+ }
32
+ }
33
+
34
+ public getViewSelectors(): Uint8Array {
35
+ const writer: BytesWriter = new BytesWriter();
36
+ writer.writeViewSelectorMap(this.selectors);
37
+
38
+ return writer.getBuffer();
39
+ }
40
+
41
+ public getMethodSelectors(): Uint8Array {
42
+ const writer: BytesWriter = new BytesWriter();
43
+ writer.writeMethodSelectorsMap(this.methodMap);
44
+
45
+ return writer.getBuffer();
46
+ }
47
+
48
+ public getWriteMethods(): Uint8Array {
49
+ const writer: BytesWriter = new BytesWriter();
50
+ writer.writeMethodSelectorsMap(this.allowedWriteMethods);
51
+
52
+ return writer.getBuffer();
53
+ }
54
+
55
+ // Register methods with their selectors and handlers
56
+ public defineMethodSelector(name: string, canWrite: boolean): void {
57
+ const selector: u32 = encodeSelector(name);
58
+ if (canWrite) this.addToWriteMethods(selector);
59
+
60
+ if (!this.methodMap.includes(selector)) {
61
+ this.methodMap.push(selector);
62
+ }
63
+ }
64
+
65
+ private addToWriteMethods(selector: Selector): void {
66
+ if (!this.allowedWriteMethods.includes(selector)) {
67
+ this.allowedWriteMethods.push(selector);
68
+ }
69
+ }
70
+ }
71
+
72
+ export const ABIRegistry = new ABIRegistryBase();