@btc-vision/btc-runtime 1.3.18 → 1.3.19

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.3.18",
3
+ "version": "1.3.19",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "scripts": {
@@ -309,10 +309,11 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
309
309
  @unsafe
310
310
  protected _unsafeTransferFrom(from: Address, to: Address, value: u256): boolean {
311
311
  const balance: u256 = this.balanceOfMap.get(from);
312
- if (balance < value)
312
+ if (balance < value) {
313
313
  throw new Revert(
314
- `TransferFrom insufficient balance of ${from} is ${balance} and value is ${value}`,
314
+ `TransferFrom insufficient balance of ${from.toHex()} is ${balance} and value is ${value}`,
315
315
  );
316
+ }
316
317
 
317
318
  const newBalance: u256 = SafeMath.sub(balance, value);
318
319
  this.balanceOfMap.set(from, newBalance);
package/runtime/index.ts CHANGED
@@ -62,22 +62,26 @@ export * from './memory/Uint8ArrayMerger';
62
62
  /** Storage */
63
63
  export * from './storage/StoredU256';
64
64
  export * from './storage/StoredU64';
65
- export * from './storage/StoredU16Array';
66
- export * from './storage/StoredU32Array';
67
- export * from './storage/StoredBooleanArray';
68
- export * from './storage/StoredU128Array';
69
- export * from './storage/StoredU256Array';
70
65
  export * from './storage/StoredString';
71
66
  export * from './storage/StoredAddress';
72
67
  export * from './storage/StoredBoolean';
73
68
  export * from './storage/Serializable';
74
- export * from './storage/StoredAddressArray';
75
69
 
76
- export * from './storage/StorageBacked';
77
- export * from './storage/StorageSlot';
78
- export * from './storage/StorageStruct';
79
- export * from './storage/StorageLayout';
80
- export * from './storage/StorageValue';
70
+ /** Arrays */
71
+ export * from './storage/arrays/StoredAddressArray';
72
+ export * from './storage/arrays/StoredU8Array';
73
+ export * from './storage/arrays/StoredU16Array';
74
+ export * from './storage/arrays/StoredU32Array';
75
+ export * from './storage/arrays/StoredBooleanArray';
76
+ export * from './storage/arrays/StoredU128Array';
77
+ export * from './storage/arrays/StoredU256Array';
78
+
79
+ /** Storage Utils */
80
+ export * from './storage/utils/StorageBacked';
81
+ export * from './storage/utils/StorageSlot';
82
+ export * from './storage/utils/StorageStruct';
83
+ export * from './storage/utils/StorageLayout';
84
+ export * from './storage/utils/StorageValue';
81
85
 
82
86
  /** Shared libraries */
83
87
  export * from './shared-libraries/TransferHelper';
@@ -1,9 +1,9 @@
1
1
  import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { BytesWriter } from '../buffer/BytesWriter';
3
- import { Blockchain } from '../env';
4
- import { Address } from '../types/Address';
5
- import { Revert } from '../types/Revert';
6
- import { SafeMath } from '../types/SafeMath';
2
+ import { BytesWriter } from '../../buffer/BytesWriter';
3
+ import { Blockchain } from '../../env';
4
+ import { Address } from '../../types/Address';
5
+ import { Revert } from '../../types/Revert';
6
+ import { SafeMath } from '../../types/SafeMath';
7
7
 
8
8
  /**
9
9
  * @class StoredAddressArray
@@ -35,7 +35,11 @@ export class StoredAddressArray {
35
35
  * @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
36
36
  * @param {Address} defaultValue - The default Address value if storage is uninitialized.
37
37
  */
38
- constructor(public pointer: u16, public subPointer: Uint8Array, private defaultValue: Address) {
38
+ constructor(
39
+ public pointer: u16,
40
+ public subPointer: Uint8Array,
41
+ private defaultValue: Address,
42
+ ) {
39
43
  // Initialize the base pointer
40
44
  const writer = new BytesWriter(32);
41
45
  writer.writeU16(pointer);
@@ -1,8 +1,8 @@
1
1
  import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { BytesWriter } from '../buffer/BytesWriter';
3
- import { Blockchain } from '../env';
4
- import { Revert } from '../types/Revert';
5
- import { SafeMath } from '../types/SafeMath';
2
+ import { BytesWriter } from '../../buffer/BytesWriter';
3
+ import { Blockchain } from '../../env';
4
+ import { Revert } from '../../types/Revert';
5
+ import { SafeMath } from '../../types/SafeMath';
6
6
 
7
7
  /**
8
8
  * @class StoredBooleanArray
@@ -33,7 +33,11 @@ export class StoredBooleanArray {
33
33
  * @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
34
34
  * @param {u256} defaultValue - The default u256 value if storage is uninitialized.
35
35
  */
36
- constructor(public pointer: u16, public subPointer: Uint8Array, private defaultValue: u256) {
36
+ constructor(
37
+ public pointer: u16,
38
+ public subPointer: Uint8Array,
39
+ private defaultValue: u256,
40
+ ) {
37
41
  // Initialize the base u256 pointer using the primary pointer and subPointer
38
42
  const writer = new BytesWriter(32);
39
43
  writer.writeU16(pointer);
@@ -1,8 +1,8 @@
1
1
  import { u128, u256 } from '@btc-vision/as-bignum/assembly';
2
- import { Blockchain } from '../env';
3
- import { BytesWriter } from '../buffer/BytesWriter';
4
- import { SafeMath } from '../types/SafeMath';
5
- import { Revert } from '../types/Revert';
2
+ import { Blockchain } from '../../env';
3
+ import { BytesWriter } from '../../buffer/BytesWriter';
4
+ import { SafeMath } from '../../types/SafeMath';
5
+ import { Revert } from '../../types/Revert';
6
6
 
7
7
  /**
8
8
  * @class StoredU128Array
@@ -1,8 +1,8 @@
1
1
  import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { Blockchain } from '../env';
3
- import { BytesWriter } from '../buffer/BytesWriter';
4
- import { SafeMath } from '../types/SafeMath';
5
- import { Revert } from '../types/Revert';
2
+ import { Blockchain } from '../../env';
3
+ import { BytesWriter } from '../../buffer/BytesWriter';
4
+ import { SafeMath } from '../../types/SafeMath';
5
+ import { Revert } from '../../types/Revert';
6
6
 
7
7
  /**
8
8
  * @class StoredU16Array
@@ -1,8 +1,8 @@
1
1
  import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { Blockchain } from '../env';
3
- import { BytesWriter } from '../buffer/BytesWriter';
4
- import { SafeMath } from '../types/SafeMath';
5
- import { Revert } from '../types/Revert';
2
+ import { Blockchain } from '../../env';
3
+ import { BytesWriter } from '../../buffer/BytesWriter';
4
+ import { SafeMath } from '../../types/SafeMath';
5
+ import { Revert } from '../../types/Revert';
6
6
 
7
7
  /**
8
8
  * @class StoredU256Array
@@ -1,8 +1,8 @@
1
1
  import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { Blockchain } from '../env';
3
- import { BytesWriter } from '../buffer/BytesWriter';
4
- import { SafeMath } from '../types/SafeMath';
5
- import { Revert } from '../types/Revert';
2
+ import { Blockchain } from '../../env';
3
+ import { BytesWriter } from '../../buffer/BytesWriter';
4
+ import { SafeMath } from '../../types/SafeMath';
5
+ import { Revert } from '../../types/Revert';
6
6
 
7
7
  /**
8
8
  * @class StoredU32Array
@@ -0,0 +1,515 @@
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
+ import { BytesWriter } from '../../buffer/BytesWriter';
3
+ import { Blockchain } from '../../env';
4
+ import { Revert } from '../../types/Revert';
5
+ import { SafeMath } from '../../types/SafeMath';
6
+
7
+ /**
8
+ * @class StoredU8Array
9
+ * @description Manages an array of u8 values across multiple storage slots. Each slot holds thirty-two u8 values packed into a u256.
10
+ */
11
+ @final
12
+ export class StoredU8Array {
13
+ private readonly baseU256Pointer: u256;
14
+ private readonly lengthPointer: u256;
15
+
16
+ // Internal cache for storage slots
17
+ private _values: Map<u64, u8[]> = new Map(); // Map from slotIndex to array of thirty-two u8s
18
+ private _isLoaded: Set<u64> = new Set(); // Set of slotIndexes that are loaded
19
+ private _isChanged: Set<u64> = new Set(); // Set of slotIndexes that are modified
20
+
21
+ // Internal variables for length and startIndex management
22
+ private _length: u64 = 0; // Current length of the array
23
+ private _startIndex: u64 = 0; // Starting index of the array
24
+ private _isChangedLength: bool = false;
25
+ private _isChangedStartIndex: bool = false;
26
+
27
+ // Define a maximum allowed length to prevent excessive storage usage
28
+ private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
29
+
30
+ /**
31
+ * @constructor
32
+ * @param {u16} pointer - The primary pointer identifier.
33
+ * @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
34
+ * @param {u256} defaultValue - The default u256 value if storage is uninitialized.
35
+ */
36
+ constructor(
37
+ public pointer: u16,
38
+ public subPointer: Uint8Array,
39
+ private defaultValue: u256,
40
+ ) {
41
+ // Initialize the base u256 pointer using the primary pointer and subPointer
42
+ const writer = new BytesWriter(32);
43
+ writer.writeU16(pointer);
44
+ writer.writeBytes(subPointer);
45
+
46
+ const baseU256Pointer = u256.fromBytes(writer.getBuffer(), true);
47
+ const lengthPointer = baseU256Pointer.clone();
48
+
49
+ // Load the current length and startIndex from storage
50
+ const storedLengthAndStartIndex: u256 = Blockchain.getStorageAt(lengthPointer, u256.Zero);
51
+ this.lengthPointer = lengthPointer;
52
+ this.baseU256Pointer = baseU256Pointer;
53
+
54
+ this._length = storedLengthAndStartIndex.lo1; // Bytes 0-7: length
55
+ this._startIndex = storedLengthAndStartIndex.lo2; // Bytes 8-15: startIndex
56
+ }
57
+
58
+ /**
59
+ * @method get
60
+ * @description Retrieves the u8 value at the specified global index.
61
+ * @param {u64} index - The global index (0 to ∞) of the u8 value to retrieve.
62
+ * @returns {u8} - The u8 value at the specified index.
63
+ */
64
+ @inline
65
+ public get(index: u64): u8 {
66
+ assert(index < this._length, 'Index out of bounds');
67
+
68
+ const slotIndex: u64 = index / 32; // Each slot holds thirty-two u8s
69
+ const subIndex: u8 = <u8>(index % 32);
70
+ this.ensureValues(slotIndex);
71
+ const slotValues = this._values.get(slotIndex);
72
+ return slotValues ? slotValues[subIndex] : 0;
73
+ }
74
+
75
+ /**
76
+ * @method set
77
+ * @description Sets the u8 value at the specified global index.
78
+ * @param {u64} index - The global index (0 to ∞) of the u8 value to set.
79
+ * @param {u8} value - The u8 value to assign.
80
+ */
81
+ @inline
82
+ public set(index: u64, value: u8): void {
83
+ assert(index < this._length, 'Index exceeds current array length');
84
+
85
+ const slotIndex: u64 = index / 32;
86
+ const subIndex: u8 = <u8>(index % 32);
87
+ this.ensureValues(slotIndex);
88
+
89
+ const slotValues = this._values.get(slotIndex);
90
+ if (slotValues && slotValues[subIndex] !== value) {
91
+ slotValues[subIndex] = value;
92
+ this._isChanged.add(slotIndex);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * @method push
98
+ * @description Appends a new u8 value to the end of the array.
99
+ * @param {u8} value - The u8 value to append.
100
+ */
101
+ public push(value: u8): void {
102
+ if (this._length >= this.MAX_LENGTH) {
103
+ throw new Revert(
104
+ 'Push operation failed: Array has reached its maximum allowed length.',
105
+ );
106
+ }
107
+
108
+ const newIndex: u64 = this._length;
109
+ const wrappedIndex: u64 =
110
+ newIndex < this.MAX_LENGTH ? newIndex : newIndex % this.MAX_LENGTH;
111
+
112
+ const slotIndex: u64 = wrappedIndex / 32;
113
+ const subIndex: u8 = <u8>(wrappedIndex % 32);
114
+
115
+ this.ensureValues(slotIndex);
116
+
117
+ const slotValues = this._values.get(slotIndex);
118
+ if (slotValues) {
119
+ slotValues[subIndex] = value;
120
+ this._isChanged.add(slotIndex);
121
+ }
122
+
123
+ this._length += 1;
124
+ this._isChangedLength = true;
125
+ }
126
+
127
+ /**
128
+ * @method delete
129
+ * @description Deletes the u8 value at the specified index by setting it to zero. Does not reorder the array.
130
+ * @param {u64} index - The global index of the u8 value to delete.
131
+ */
132
+ public delete(index: u64): void {
133
+ if (index >= this._length) {
134
+ throw new Revert('Delete operation failed: Index out of bounds.');
135
+ }
136
+
137
+ const slotIndex: u64 = index / 32;
138
+ const subIndex: u8 = <u8>(index % 32);
139
+ this.ensureValues(slotIndex);
140
+
141
+ const slotValues = this._values.get(slotIndex);
142
+ if (slotValues && slotValues[subIndex] !== 0) {
143
+ slotValues[subIndex] = 0;
144
+ this._isChanged.add(slotIndex);
145
+ }
146
+ }
147
+
148
+ /**
149
+ * @method shift
150
+ * @description Removes the first element of the array by setting it to zero, decrementing the length,
151
+ * and incrementing the startIndex (with wrap-around if needed).
152
+ */
153
+ public shift(): void {
154
+ if (this._length === 0) {
155
+ throw new Revert('Shift operation failed: Array is empty.');
156
+ }
157
+
158
+ const currentStartIndex: u64 = this._startIndex;
159
+ const slotIndex: u64 = currentStartIndex / 32;
160
+ const subIndex: u8 = <u8>(currentStartIndex % 32);
161
+ this.ensureValues(slotIndex);
162
+
163
+ const slotValues = this._values.get(slotIndex);
164
+ if (slotValues && slotValues[subIndex] !== 0) {
165
+ slotValues[subIndex] = 0;
166
+ this._isChanged.add(slotIndex);
167
+ }
168
+
169
+ this._length -= 1;
170
+ this._isChangedLength = true;
171
+
172
+ if (this._startIndex < this.MAX_LENGTH - 1) {
173
+ this._startIndex += 1;
174
+ } else {
175
+ this._startIndex = 0;
176
+ }
177
+ this._isChangedStartIndex = true;
178
+ }
179
+
180
+ /**
181
+ * @method save
182
+ * @description Persists all cached u8 values, the length, and the startIndex to their respective storage slots if any have been modified.
183
+ */
184
+ public save(): void {
185
+ // Save all changed slots
186
+ const changedSlots = this._isChanged.values();
187
+ for (let i = 0; i < changedSlots.length; i++) {
188
+ const slotIndex = changedSlots[i];
189
+ const packed = this.packValues(slotIndex);
190
+ const storagePointer = this.calculateStoragePointer(slotIndex);
191
+ Blockchain.setStorageAt(storagePointer, packed);
192
+ }
193
+ this._isChanged.clear();
194
+
195
+ // Save length and startIndex if changed
196
+ if (this._isChangedLength || this._isChangedStartIndex) {
197
+ const packedLengthAndStartIndex = new u256();
198
+ packedLengthAndStartIndex.lo1 = this._length;
199
+ packedLengthAndStartIndex.lo2 = this._startIndex;
200
+ Blockchain.setStorageAt(this.lengthPointer, packedLengthAndStartIndex);
201
+ this._isChangedLength = false;
202
+ this._isChangedStartIndex = false;
203
+ }
204
+ }
205
+
206
+ /**
207
+ * @method deleteAll
208
+ * @description Deletes all storage slots by setting them to zero, including the length and startIndex slots.
209
+ */
210
+ public deleteAll(): void {
211
+ // Iterate over all loaded slots and clear them
212
+ const keys = this._values.keys();
213
+ for (let i = 0; i < keys.length; i++) {
214
+ const slotIndex = keys[i];
215
+ const storagePointer = this.calculateStoragePointer(slotIndex);
216
+ Blockchain.setStorageAt(storagePointer, u256.Zero);
217
+ }
218
+
219
+ // Reset length and startIndex
220
+ Blockchain.setStorageAt(this.lengthPointer, u256.Zero);
221
+ this._length = 0;
222
+ this._startIndex = 0;
223
+ this._isChangedLength = false;
224
+ this._isChangedStartIndex = false;
225
+
226
+ // Clear internal caches
227
+ this._values.clear();
228
+ this._isLoaded.clear();
229
+ this._isChanged.clear();
230
+ }
231
+
232
+ /**
233
+ * @method setMultiple
234
+ * @description Sets multiple u8 values starting from a specific global index.
235
+ * @param {u64} startIndex - The starting global index.
236
+ * @param {u8[]} values - An array of u8 values to set.
237
+ */
238
+ @inline
239
+ public setMultiple(startIndex: u64, values: u8[]): void {
240
+ for (let i: u64 = 0; i < values.length; i++) {
241
+ this.set(startIndex + i, values[i]);
242
+ }
243
+ }
244
+
245
+ /**
246
+ * @method getAll
247
+ * @description Retrieves a range of u8 values starting from a specific global index.
248
+ * @param {u64} startIndex - The starting global index.
249
+ * @param {u64} count - The number of u8 values to retrieve.
250
+ * @returns {u8[]} - An array containing the retrieved u8 values.
251
+ */
252
+ @inline
253
+ public getAll(startIndex: u64, count: u64): u8[] {
254
+ assert(startIndex + count <= this._length, 'Requested range exceeds array length');
255
+ if (u32.MAX_VALUE < count) {
256
+ throw new Revert('Requested range exceeds maximum allowed value.');
257
+ }
258
+
259
+ const result: u8[] = new Array<u8>(count as u32);
260
+ for (let i: u64 = 0; i < count; i++) {
261
+ result[i as u32] = this.get(startIndex + i);
262
+ }
263
+ return result;
264
+ }
265
+
266
+ /**
267
+ * @method toString
268
+ * @description Returns a string representation of all cached u8 values.
269
+ * @returns {string} - A string in the format "[value0, value1, ..., valueN]".
270
+ */
271
+ @inline
272
+ public toString(): string {
273
+ let str = '[';
274
+ for (let i: u64 = 0; i < this._length; i++) {
275
+ const value = this.get(i);
276
+ str += value.toString();
277
+ if (i !== this._length - 1) {
278
+ str += ', ';
279
+ }
280
+ }
281
+ str += ']';
282
+ return str;
283
+ }
284
+
285
+ /**
286
+ * @method toBytes
287
+ * @description Returns the packed u256 values as a byte array.
288
+ * @returns {u8[]} - The packed u256 values in byte form.
289
+ */
290
+ @inline
291
+ public toBytes(): u8[] {
292
+ const bytes: u8[] = new Array<u8>();
293
+ const slotCount: u64 = (this._length + 31) / 32;
294
+
295
+ for (let slotIndex: u64 = 0; slotIndex < slotCount; slotIndex++) {
296
+ this.ensureValues(slotIndex);
297
+ const packed = this.packValues(slotIndex);
298
+ const slotBytes = packed.toBytes();
299
+ for (let i: u32 = 0; i < slotBytes.length; i++) {
300
+ bytes.push(slotBytes[i]);
301
+ }
302
+ }
303
+ return bytes;
304
+ }
305
+
306
+ /**
307
+ * @method reset
308
+ * @description Resets all cached u8 values to zero and marks them as changed, including resetting the length and startIndex.
309
+ */
310
+ @inline
311
+ public reset(): void {
312
+ this._length = 0;
313
+ this._startIndex = 0;
314
+ this._isChangedLength = true;
315
+ this._isChangedStartIndex = true;
316
+ this.save();
317
+ }
318
+
319
+ /**
320
+ * @method getLength
321
+ * @description Retrieves the current length of the array.
322
+ * @returns {u64} - The current length.
323
+ */
324
+ @inline
325
+ public getLength(): u64 {
326
+ return this._length;
327
+ }
328
+
329
+ /**
330
+ * @method startingIndex
331
+ * @description Retrieves the current starting index of the array.
332
+ * @returns {u64} - The starting index.
333
+ */
334
+ public startingIndex(): u64 {
335
+ return this._startIndex;
336
+ }
337
+
338
+ /**
339
+ * @method setLength
340
+ * @description Sets the length of the array.
341
+ * @param {u64} newLength - The new length to set.
342
+ */
343
+ public setLength(newLength: u64): void {
344
+ if (newLength > this.MAX_LENGTH) {
345
+ throw new Revert('SetLength operation failed: Length exceeds maximum allowed value.');
346
+ }
347
+
348
+ // If newLength is bigger than _startIndex, adjust startIndex
349
+ if (newLength > this._startIndex) {
350
+ this._startIndex = newLength;
351
+ this._isChangedStartIndex = true;
352
+ }
353
+
354
+ this._length = newLength;
355
+ this._isChangedLength = true;
356
+ }
357
+
358
+ /**
359
+ * @method deleteLast
360
+ * @description Removes the last element of the array by setting it to zero and decrementing the length.
361
+ */
362
+ public deleteLast(): void {
363
+ if (this._length === 0) {
364
+ throw new Revert('DeleteLast operation failed: Array is empty.');
365
+ }
366
+
367
+ const index = this._length - 1;
368
+ this.delete(index);
369
+
370
+ this._length -= 1;
371
+ this._isChangedLength = true;
372
+ }
373
+
374
+ /**
375
+ * @private
376
+ * @method ensureValues
377
+ * @description Loads and caches the u8 values from the specified storage slot if not already loaded.
378
+ * @param {u64} slotIndex - The index of the storage slot.
379
+ */
380
+ private ensureValues(slotIndex: u64): void {
381
+ if (!this._isLoaded.has(slotIndex)) {
382
+ const storagePointer = this.calculateStoragePointer(slotIndex);
383
+ const storedU256: u256 = Blockchain.getStorageAt(storagePointer, this.defaultValue);
384
+ const slotValues = this.unpackU256(storedU256);
385
+ this._values.set(slotIndex, slotValues);
386
+ this._isLoaded.add(slotIndex);
387
+ }
388
+ }
389
+
390
+ /**
391
+ * @private
392
+ * @method packValues
393
+ * @description Packs the thirty-two cached u8 values into a single u256 for storage.
394
+ * @param {u64} slotIndex - The index of the storage slot.
395
+ * @returns {u256} - The packed u256 value.
396
+ */
397
+ private packValues(slotIndex: u64): u256 {
398
+ const values = this._values.get(slotIndex);
399
+ if (!values) {
400
+ return u256.Zero;
401
+ }
402
+ const packed = new u256();
403
+
404
+ // Pack values[0..7] into lo1
405
+ packed.lo1 =
406
+ (u64(values[0]) << 56) |
407
+ (u64(values[1]) << 48) |
408
+ (u64(values[2]) << 40) |
409
+ (u64(values[3]) << 32) |
410
+ (u64(values[4]) << 24) |
411
+ (u64(values[5]) << 16) |
412
+ (u64(values[6]) << 8) |
413
+ u64(values[7]);
414
+
415
+ // Pack values[8..15] into lo2
416
+ packed.lo2 =
417
+ (u64(values[8]) << 56) |
418
+ (u64(values[9]) << 48) |
419
+ (u64(values[10]) << 40) |
420
+ (u64(values[11]) << 32) |
421
+ (u64(values[12]) << 24) |
422
+ (u64(values[13]) << 16) |
423
+ (u64(values[14]) << 8) |
424
+ u64(values[15]);
425
+
426
+ // Pack values[16..23] into hi1
427
+ packed.hi1 =
428
+ (u64(values[16]) << 56) |
429
+ (u64(values[17]) << 48) |
430
+ (u64(values[18]) << 40) |
431
+ (u64(values[19]) << 32) |
432
+ (u64(values[20]) << 24) |
433
+ (u64(values[21]) << 16) |
434
+ (u64(values[22]) << 8) |
435
+ u64(values[23]);
436
+
437
+ // Pack values[24..31] into hi2
438
+ packed.hi2 =
439
+ (u64(values[24]) << 56) |
440
+ (u64(values[25]) << 48) |
441
+ (u64(values[26]) << 40) |
442
+ (u64(values[27]) << 32) |
443
+ (u64(values[28]) << 24) |
444
+ (u64(values[29]) << 16) |
445
+ (u64(values[30]) << 8) |
446
+ u64(values[31]);
447
+
448
+ return packed;
449
+ }
450
+
451
+ /**
452
+ * @private
453
+ * @method unpackU256
454
+ * @description Unpacks a u256 value into an array of thirty-two u8s.
455
+ * @param {u256} storedU256 - The u256 value to unpack.
456
+ * @returns {u8[]} - An array of thirty-two u8 values.
457
+ */
458
+ private unpackU256(storedU256: u256): u8[] {
459
+ const values: u8[] = new Array<u8>(32);
460
+
461
+ // Unpack lo1 into values[0..7]
462
+ values[0] = u8(storedU256.lo1 >> 56);
463
+ values[1] = u8((storedU256.lo1 >> 48) & 0xff);
464
+ values[2] = u8((storedU256.lo1 >> 40) & 0xff);
465
+ values[3] = u8((storedU256.lo1 >> 32) & 0xff);
466
+ values[4] = u8((storedU256.lo1 >> 24) & 0xff);
467
+ values[5] = u8((storedU256.lo1 >> 16) & 0xff);
468
+ values[6] = u8((storedU256.lo1 >> 8) & 0xff);
469
+ values[7] = u8(storedU256.lo1 & 0xff);
470
+
471
+ // Unpack lo2 into values[8..15]
472
+ values[8] = u8(storedU256.lo2 >> 56);
473
+ values[9] = u8((storedU256.lo2 >> 48) & 0xff);
474
+ values[10] = u8((storedU256.lo2 >> 40) & 0xff);
475
+ values[11] = u8((storedU256.lo2 >> 32) & 0xff);
476
+ values[12] = u8((storedU256.lo2 >> 24) & 0xff);
477
+ values[13] = u8((storedU256.lo2 >> 16) & 0xff);
478
+ values[14] = u8((storedU256.lo2 >> 8) & 0xff);
479
+ values[15] = u8(storedU256.lo2 & 0xff);
480
+
481
+ // Unpack hi1 into values[16..23]
482
+ values[16] = u8(storedU256.hi1 >> 56);
483
+ values[17] = u8((storedU256.hi1 >> 48) & 0xff);
484
+ values[18] = u8((storedU256.hi1 >> 40) & 0xff);
485
+ values[19] = u8((storedU256.hi1 >> 32) & 0xff);
486
+ values[20] = u8((storedU256.hi1 >> 24) & 0xff);
487
+ values[21] = u8((storedU256.hi1 >> 16) & 0xff);
488
+ values[22] = u8((storedU256.hi1 >> 8) & 0xff);
489
+ values[23] = u8(storedU256.hi1 & 0xff);
490
+
491
+ // Unpack hi2 into values[24..31]
492
+ values[24] = u8(storedU256.hi2 >> 56);
493
+ values[25] = u8((storedU256.hi2 >> 48) & 0xff);
494
+ values[26] = u8((storedU256.hi2 >> 40) & 0xff);
495
+ values[27] = u8((storedU256.hi2 >> 32) & 0xff);
496
+ values[28] = u8((storedU256.hi2 >> 24) & 0xff);
497
+ values[29] = u8((storedU256.hi2 >> 16) & 0xff);
498
+ values[30] = u8((storedU256.hi2 >> 8) & 0xff);
499
+ values[31] = u8(storedU256.hi2 & 0xff);
500
+
501
+ return values;
502
+ }
503
+
504
+ /**
505
+ * @private
506
+ * @method calculateStoragePointer
507
+ * @description Calculates the storage pointer for a given slot index by incrementing the base pointer.
508
+ * @param {u64} slotIndex - The index of the storage slot.
509
+ * @returns {u256} - The calculated storage pointer.
510
+ */
511
+ private calculateStoragePointer(slotIndex: u64): u256 {
512
+ // Each slot is identified by baseU256Pointer + slotIndex + 1
513
+ return SafeMath.add(this.baseU256Pointer, u256.fromU64(slotIndex + 1));
514
+ }
515
+ }
@@ -1,4 +1,4 @@
1
- import { Blockchain } from '../env';
1
+ import { Blockchain } from '../../env';
2
2
 
3
3
  export class StorageLayout {
4
4
  public next(): u16 {
@@ -1,8 +1,8 @@
1
1
  import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { BlockchainEnvironment } from '../env/BlockchainEnvironment';
3
- import { Sha256 } from '../math/sha256';
4
- import { MemorySlotPointer } from '../memory/MemorySlotPointer';
5
- import { Box, concat, fromArrayBuffer, toArrayBuffer } from '../utils';
2
+ import { BlockchainEnvironment } from '../../env/BlockchainEnvironment';
3
+ import { Sha256 } from '../../math/sha256';
4
+ import { MemorySlotPointer } from '../../memory/MemorySlotPointer';
5
+ import { Box, concat, fromArrayBuffer, toArrayBuffer } from '../../utils';
6
6
 
7
7
  export function toBuffer<T>(v: T): ArrayBuffer {
8
8
  const result = new ArrayBuffer(sizeof<T>());
@@ -411,4 +411,12 @@ export class SafeMath {
411
411
 
412
412
  return result;
413
413
  }
414
+
415
+ public static pow10(exponent: u8): u256 {
416
+ let result: u256 = u256.One;
417
+ for (let i: u8 = 0; i < exponent; i++) {
418
+ result = SafeMath.mul(result, u256.fromU32(10));
419
+ }
420
+ return result;
421
+ }
414
422
  }