@btc-vision/btc-runtime 1.9.0 → 1.9.2
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/package.json +13 -4
- package/runtime/constants/Exports.ts +86 -0
- package/runtime/contracts/OP1155.ts +1042 -0
- package/runtime/contracts/OP20.ts +64 -38
- package/runtime/contracts/OP721.ts +882 -0
- package/runtime/contracts/OP_NET.ts +5 -0
- package/runtime/contracts/ReentrancyGuard.ts +136 -0
- package/runtime/contracts/interfaces/IOP1155.ts +33 -0
- package/runtime/contracts/interfaces/IOP721.ts +29 -0
- package/runtime/contracts/interfaces/OP1155InitParameters.ts +11 -0
- package/runtime/contracts/interfaces/OP721InitParameters.ts +15 -0
- package/runtime/env/BlockchainEnvironment.ts +32 -3
- package/runtime/events/predefined/ApprovedForAll.ts +16 -0
- package/runtime/events/predefined/TransferredBatchEvent.ts +35 -0
- package/runtime/events/predefined/TransferredSingleEvent.ts +18 -0
- package/runtime/events/predefined/URIEvent.ts +23 -0
- package/runtime/events/predefined/index.ts +4 -0
- package/runtime/index.ts +9 -0
- package/runtime/math/abi.ts +23 -0
- package/runtime/math/bytes.ts +4 -0
- package/runtime/memory/AddressMemoryMap.ts +20 -0
- package/runtime/nested/storage/StorageMap.ts +3 -23
- package/runtime/nested/storage/StorageSet.ts +6 -3
- package/runtime/script/Script.ts +1 -1
- package/runtime/secp256k1/ECPoint.ts +3 -3
- package/runtime/shared-libraries/OP20Utils.ts +1 -2
- package/runtime/storage/AdvancedStoredString.ts +8 -189
- package/runtime/storage/BaseStoredString.ts +206 -0
- package/runtime/storage/StoredString.ts +15 -194
- package/runtime/storage/arrays/StoredPackedArray.ts +19 -5
- package/runtime/types/SafeMath.ts +125 -94
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
bigEndianAdd,
|
|
3
|
+
GET_EMPTY_BUFFER,
|
|
4
|
+
readLengthAndStartIndex,
|
|
5
|
+
writeLengthAndStartIndex,
|
|
6
|
+
} from '../../math/bytes';
|
|
2
7
|
import { Blockchain } from '../../env';
|
|
3
8
|
import { Revert } from '../../types/Revert';
|
|
4
9
|
import { encodePointer } from '../../math/abi';
|
|
@@ -87,7 +92,8 @@ export abstract class StoredPackedArray<T> {
|
|
|
87
92
|
@operator('[]')
|
|
88
93
|
public get(index: u32): T {
|
|
89
94
|
// max length used on purpose to prevent unbounded usage
|
|
90
|
-
|
|
95
|
+
// we allow index to be equal to MAX_LENGTH because, we allow it on the set as well.
|
|
96
|
+
if (index >= this.MAX_LENGTH) {
|
|
91
97
|
throw new Revert('get: out of range');
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -104,7 +110,7 @@ export abstract class StoredPackedArray<T> {
|
|
|
104
110
|
|
|
105
111
|
@inline
|
|
106
112
|
public get_physical(index: u32): T {
|
|
107
|
-
if (index
|
|
113
|
+
if (index >= this.MAX_LENGTH) {
|
|
108
114
|
throw new Revert('get: index exceeds MAX_LENGTH (packed array)');
|
|
109
115
|
}
|
|
110
116
|
|
|
@@ -121,7 +127,7 @@ export abstract class StoredPackedArray<T> {
|
|
|
121
127
|
@inline
|
|
122
128
|
@operator('[]=')
|
|
123
129
|
public set(index: u32, value: T): void {
|
|
124
|
-
if (index
|
|
130
|
+
if (index >= this.MAX_LENGTH) {
|
|
125
131
|
throw new Revert('set: index exceeds MAX_LENGTH (packed array)');
|
|
126
132
|
}
|
|
127
133
|
|
|
@@ -143,7 +149,7 @@ export abstract class StoredPackedArray<T> {
|
|
|
143
149
|
|
|
144
150
|
@inline
|
|
145
151
|
public set_physical(index: u32, value: T): void {
|
|
146
|
-
if (index
|
|
152
|
+
if (index >= this.MAX_LENGTH) {
|
|
147
153
|
throw new Revert('set: index exceeds MAX_LENGTH (packed array)');
|
|
148
154
|
}
|
|
149
155
|
|
|
@@ -298,6 +304,10 @@ export abstract class StoredPackedArray<T> {
|
|
|
298
304
|
*/
|
|
299
305
|
@inline
|
|
300
306
|
public delete_physical(index: u32): void {
|
|
307
|
+
if (index >= this.MAX_LENGTH) {
|
|
308
|
+
throw new Revert('delete: index exceeds MAX_LENGTH (packed array)');
|
|
309
|
+
}
|
|
310
|
+
|
|
301
311
|
const cap = this.getSlotCapacity();
|
|
302
312
|
const slotIndex = index / cap;
|
|
303
313
|
const subIndex = <u32>(index % cap);
|
|
@@ -368,6 +378,10 @@ export abstract class StoredPackedArray<T> {
|
|
|
368
378
|
|
|
369
379
|
@inline
|
|
370
380
|
public setStartingIndex(index: u32): void {
|
|
381
|
+
if (index >= this.MAX_LENGTH) {
|
|
382
|
+
throw new Revert('setStartingIndex: out of range');
|
|
383
|
+
}
|
|
384
|
+
|
|
371
385
|
this._startIndex = index;
|
|
372
386
|
this._isChangedStartIndex = true;
|
|
373
387
|
}
|
|
@@ -54,13 +54,38 @@ export class SafeMath {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// Computes (a * b) % modulus with full precision
|
|
57
|
-
public static mulmod(a: u256, b: u256, modulus: u256): u256 {
|
|
57
|
+
/*public static mulmod(a: u256, b: u256, modulus: u256): u256 {
|
|
58
58
|
if (u256.eq(modulus, u256.Zero)) throw new Revert('SafeMath: modulo by zero');
|
|
59
59
|
|
|
60
60
|
const mul = SafeMath.mul(a, b);
|
|
61
61
|
return SafeMath.mod(mul, modulus);
|
|
62
|
+
}*/ // CAN OVERFLOW!
|
|
63
|
+
|
|
64
|
+
public static mulmod(a: u256, b: u256, modulus: u256): u256 {
|
|
65
|
+
if (u256.eq(modulus, u256.Zero)) throw new Revert('SafeMath: modulo by zero');
|
|
66
|
+
|
|
67
|
+
// Keep invariants: 0 <= a,b < modulus
|
|
68
|
+
a = SafeMath.mod(a, modulus);
|
|
69
|
+
b = SafeMath.mod(b, modulus);
|
|
70
|
+
if (a.isZero() || b.isZero()) return u256.Zero;
|
|
71
|
+
|
|
72
|
+
let res = u256.Zero;
|
|
73
|
+
|
|
74
|
+
// LSB-first ladder: at most 256 iterations; all steps keep values < modulus.
|
|
75
|
+
while (!b.isZero()) {
|
|
76
|
+
if (u256.ne(u256.and(b, u256.One), u256.Zero)) {
|
|
77
|
+
res = SafeMath.addModNoCarry(res, a, modulus); // res = (res + a) % m, no overflow
|
|
78
|
+
}
|
|
79
|
+
b = u256.shr(b, 1);
|
|
80
|
+
if (!b.isZero()) {
|
|
81
|
+
a = SafeMath.doubleModNoCarry(a, modulus); // a = (2a) % m, no overflow
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return res;
|
|
62
85
|
}
|
|
63
86
|
|
|
87
|
+
// (x + y) % m without ever computing a potentially-overflowing x + y.
|
|
88
|
+
|
|
64
89
|
@unsafe
|
|
65
90
|
@operator('%')
|
|
66
91
|
public static mod(a: u256, b: u256): u256 {
|
|
@@ -73,38 +98,89 @@ export class SafeMath {
|
|
|
73
98
|
return SafeMath.sub(a, product);
|
|
74
99
|
}
|
|
75
100
|
|
|
101
|
+
// (2x) % m without overflow.
|
|
102
|
+
|
|
76
103
|
public static modInverse(k: u256, p: u256): u256 {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
// Input validation
|
|
105
|
+
if (p.isZero() || u256.eq(p, u256.One)) {
|
|
106
|
+
throw new Revert('SafeMath: modulus must be > 1');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (k.isZero()) {
|
|
110
|
+
throw new Revert('SafeMath: no inverse for zero');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let s: u256 = u256.Zero;
|
|
114
|
+
let old_s: u256 = u256.One;
|
|
115
|
+
let s_negative: boolean = false;
|
|
116
|
+
let old_s_negative: boolean = false;
|
|
117
|
+
let r: u256 = p.clone();
|
|
118
|
+
let old_r: u256 = k.clone();
|
|
81
119
|
|
|
82
120
|
while (!r.isZero()) {
|
|
83
121
|
const quotient = SafeMath.div(old_r, r);
|
|
84
122
|
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
123
|
+
// Update r (always remains positive)
|
|
124
|
+
const tmp_r = r.clone();
|
|
125
|
+
r = SafeMath.sub(old_r, SafeMath.mul(quotient, r));
|
|
126
|
+
old_r = tmp_r;
|
|
127
|
+
|
|
128
|
+
// Update s with correct sign tracking
|
|
129
|
+
const tmp_s = s.clone();
|
|
130
|
+
const tmp_s_negative = s_negative;
|
|
131
|
+
const product = SafeMath.mul(quotient, s);
|
|
132
|
+
|
|
133
|
+
// Compute: old_s - (quotient * s)
|
|
134
|
+
// Taking into account the signs of old_s and s
|
|
135
|
+
|
|
136
|
+
if (!old_s_negative && !s_negative) {
|
|
137
|
+
// (+old_s) - (+product)
|
|
138
|
+
if (u256.ge(old_s, product)) {
|
|
139
|
+
s = SafeMath.sub(old_s, product);
|
|
140
|
+
s_negative = false;
|
|
141
|
+
} else {
|
|
142
|
+
s = SafeMath.sub(product, old_s);
|
|
143
|
+
s_negative = true;
|
|
144
|
+
}
|
|
145
|
+
} else if (old_s_negative && s_negative) {
|
|
146
|
+
// (-old_s) - (-product) = -old_s + product
|
|
147
|
+
if (u256.ge(product, old_s)) {
|
|
148
|
+
s = SafeMath.sub(product, old_s);
|
|
149
|
+
s_negative = false;
|
|
150
|
+
} else {
|
|
151
|
+
s = SafeMath.sub(old_s, product);
|
|
152
|
+
s_negative = true;
|
|
153
|
+
}
|
|
154
|
+
} else if (!old_s_negative && s_negative) {
|
|
155
|
+
// (+old_s) - (-product) = old_s + product
|
|
156
|
+
s = SafeMath.add(old_s, product);
|
|
157
|
+
s_negative = false;
|
|
158
|
+
} else {
|
|
159
|
+
// old_s_negative && !s_negative
|
|
160
|
+
// (-old_s) - (+product) = -(old_s + product)
|
|
161
|
+
s = SafeMath.add(old_s, product);
|
|
162
|
+
s_negative = true;
|
|
91
163
|
}
|
|
92
164
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// old_s - (quotient * s)
|
|
96
|
-
const tmp = s;
|
|
97
|
-
s = u256.sub(old_s, u256.mul(quotient, s)); // unchecked subtract
|
|
98
|
-
old_s = tmp;
|
|
99
|
-
}
|
|
165
|
+
old_s = tmp_s;
|
|
166
|
+
old_s_negative = tmp_s_negative;
|
|
100
167
|
}
|
|
101
168
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
169
|
+
// Check if inverse exists (gcd must be 1)
|
|
170
|
+
if (!u256.eq(old_r, u256.One)) {
|
|
171
|
+
throw new Revert('SafeMath: no modular inverse exists');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Reduce modulo p, handling negative values
|
|
175
|
+
if (old_s_negative) {
|
|
176
|
+
// For negative values: result = p - (|old_s| mod p)
|
|
177
|
+
const mod_result = SafeMath.mod(old_s, p);
|
|
178
|
+
if (mod_result.isZero()) {
|
|
179
|
+
return u256.Zero;
|
|
180
|
+
}
|
|
181
|
+
return SafeMath.sub(p, mod_result);
|
|
182
|
+
}
|
|
105
183
|
|
|
106
|
-
// The extended Euclidean algorithm says `old_s` is the inverse (possibly negative),
|
|
107
|
-
// so we reduce mod p
|
|
108
184
|
return SafeMath.mod(old_s, p);
|
|
109
185
|
}
|
|
110
186
|
|
|
@@ -126,31 +202,23 @@ export class SafeMath {
|
|
|
126
202
|
}
|
|
127
203
|
|
|
128
204
|
public static mul(a: u256, b: u256): u256 {
|
|
129
|
-
if (a
|
|
130
|
-
return SafeMath.ZERO;
|
|
131
|
-
}
|
|
205
|
+
if (a.isZero() || b.isZero()) return u256.Zero;
|
|
132
206
|
|
|
133
|
-
const c
|
|
134
|
-
const d
|
|
207
|
+
const c = u256.mul(a, b);
|
|
208
|
+
const d = SafeMath.div(c, a);
|
|
135
209
|
|
|
136
|
-
if (u256.ne(d, b))
|
|
137
|
-
throw new Revert('SafeMath: multiplication overflow');
|
|
138
|
-
}
|
|
210
|
+
if (u256.ne(d, b)) throw new Revert('SafeMath: multiplication overflow');
|
|
139
211
|
|
|
140
212
|
return c;
|
|
141
213
|
}
|
|
142
214
|
|
|
143
215
|
public static mul128(a: u128, b: u128): u128 {
|
|
144
|
-
if (a
|
|
145
|
-
return u128.Zero;
|
|
146
|
-
}
|
|
216
|
+
if (a.isZero() || b.isZero()) return u128.Zero;
|
|
147
217
|
|
|
148
|
-
const c
|
|
149
|
-
const d
|
|
218
|
+
const c = u128.mul(a, b);
|
|
219
|
+
const d = SafeMath.div128(c, a);
|
|
150
220
|
|
|
151
|
-
if (u128.ne(d, b))
|
|
152
|
-
throw new Revert('SafeMath: multiplication overflow');
|
|
153
|
-
}
|
|
221
|
+
if (u128.ne(d, b)) throw new Revert('SafeMath: multiplication overflow');
|
|
154
222
|
|
|
155
223
|
return c;
|
|
156
224
|
}
|
|
@@ -371,66 +439,12 @@ export class SafeMath {
|
|
|
371
439
|
return u256.xor(a, b);
|
|
372
440
|
}
|
|
373
441
|
|
|
374
|
-
public static shr(a: u256, shift: i32): u256 {
|
|
375
|
-
shift &= 255;
|
|
376
|
-
if (shift == 0) return a;
|
|
377
|
-
|
|
378
|
-
const w = shift >>> 6; // how many full 64-bit words to drop
|
|
379
|
-
const b = shift & 63; // how many bits to shift within a word
|
|
380
|
-
|
|
381
|
-
// Extract the words
|
|
382
|
-
let lo1 = a.lo1;
|
|
383
|
-
let lo2 = a.lo2;
|
|
384
|
-
let hi1 = a.hi1;
|
|
385
|
-
let hi2 = a.hi2;
|
|
386
|
-
|
|
387
|
-
// Shift words down by w words
|
|
388
|
-
// For w = 1, move lo2->lo1, hi1->lo2, hi2->hi1, and hi2 = 0
|
|
389
|
-
// For w = 2, move hi1->lo1, hi2->lo2, and zeros in hi1, hi2
|
|
390
|
-
// For w = 3, move hi2->lo1 and zeros in others
|
|
391
|
-
// For w >= 4, everything is zero.
|
|
392
|
-
if (w >= 4) {
|
|
393
|
-
// Shifting by >= 256 bits zeros out everything
|
|
394
|
-
return u256.Zero;
|
|
395
|
-
} else if (w == 3) {
|
|
396
|
-
lo1 = hi2;
|
|
397
|
-
lo2 = 0;
|
|
398
|
-
hi1 = 0;
|
|
399
|
-
hi2 = 0;
|
|
400
|
-
} else if (w == 2) {
|
|
401
|
-
lo1 = hi1;
|
|
402
|
-
lo2 = hi2;
|
|
403
|
-
hi1 = 0;
|
|
404
|
-
hi2 = 0;
|
|
405
|
-
} else if (w == 1) {
|
|
406
|
-
lo1 = lo2;
|
|
407
|
-
lo2 = hi1;
|
|
408
|
-
hi1 = hi2;
|
|
409
|
-
hi2 = 0;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// Now apply the bit shift b
|
|
413
|
-
if (b > 0) {
|
|
414
|
-
// Bring down bits from the higher word
|
|
415
|
-
const carryLo2 = hi1 << (64 - b);
|
|
416
|
-
const carryLo1 = lo2 << (64 - b);
|
|
417
|
-
const carryHi1 = hi2 << (64 - b);
|
|
418
|
-
|
|
419
|
-
lo1 = (lo1 >>> b) | carryLo1;
|
|
420
|
-
lo2 = (lo2 >>> b) | carryLo2;
|
|
421
|
-
hi1 = (hi1 >>> b) | carryHi1;
|
|
422
|
-
hi2 = hi2 >>> b;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
return new u256(lo1, lo2, hi1, hi2);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
442
|
/**
|
|
429
443
|
* Increment a u256 value by 1
|
|
430
444
|
* @param value The value to increment
|
|
431
445
|
* @returns The incremented value
|
|
432
446
|
*/
|
|
433
|
-
static inc(value: u256): u256 {
|
|
447
|
+
public static inc(value: u256): u256 {
|
|
434
448
|
if (u256.eq(value, u256.Max)) {
|
|
435
449
|
throw new Revert('SafeMath: increment overflow');
|
|
436
450
|
}
|
|
@@ -451,6 +465,11 @@ export class SafeMath {
|
|
|
451
465
|
return value.preDec();
|
|
452
466
|
}
|
|
453
467
|
|
|
468
|
+
@inline
|
|
469
|
+
public static shr(value: u256, shift: i32): u256 {
|
|
470
|
+
return u256.shr(value, shift);
|
|
471
|
+
}
|
|
472
|
+
|
|
454
473
|
/**
|
|
455
474
|
* Approximates the binary logarithm (log2) of a u256 integer.
|
|
456
475
|
* @param x - The input value for which to calculate log2(x).
|
|
@@ -591,6 +610,18 @@ export class SafeMath {
|
|
|
591
610
|
return term1 - z2Div + z3Div;
|
|
592
611
|
}
|
|
593
612
|
|
|
613
|
+
// Pre: 0 <= x,y < m, m > 0.
|
|
614
|
+
private static addModNoCarry(x: u256, y: u256, m: u256): u256 {
|
|
615
|
+
const mMinusY = SafeMath.sub(m, y); // safe since y < m
|
|
616
|
+
return u256.ge(x, mMinusY) ? SafeMath.sub(x, mMinusY) : SafeMath.add(x, y);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Pre: 0 <= x < m, m > 0.
|
|
620
|
+
private static doubleModNoCarry(x: u256, m: u256): u256 {
|
|
621
|
+
const mMinusX = SafeMath.sub(m, x); // safe since x < m
|
|
622
|
+
return u256.ge(x, mMinusX) ? SafeMath.sub(x, mMinusX) : SafeMath.add(x, x);
|
|
623
|
+
}
|
|
624
|
+
|
|
594
625
|
private static bitLength64(value: u64): u32 {
|
|
595
626
|
if (value == 0) return 0;
|
|
596
627
|
|