@btc-vision/btc-runtime 1.4.7 → 1.5.1
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 +44 -53
- package/runtime/abort/abort.ts +25 -0
- package/runtime/buffer/BytesReader.ts +171 -140
- package/runtime/buffer/BytesWriter.ts +120 -152
- package/runtime/contracts/DeployableOP_20.ts +29 -15
- package/runtime/contracts/OP_NET.ts +4 -1
- package/runtime/env/BlockchainEnvironment.ts +79 -137
- package/runtime/env/classes/Block.ts +4 -8
- package/runtime/env/classes/Transaction.ts +14 -7
- package/runtime/env/classes/UTXO.ts +4 -2
- package/runtime/env/global.ts +49 -20
- package/runtime/events/predefined/MintEvent.ts +1 -1
- package/runtime/exports/index.ts +33 -8
- package/runtime/generic/AddressMap.ts +7 -5
- package/runtime/generic/Map.ts +32 -2
- package/runtime/generic/MapU256.ts +7 -5
- package/runtime/generic/MapUint8Array.ts +93 -0
- package/runtime/index.ts +4 -12
- package/runtime/math/abi.ts +71 -11
- package/runtime/math/bytes.ts +177 -41
- package/runtime/memory/AddressMemoryMap.ts +22 -19
- package/runtime/memory/FastUint8Array.ts +122 -0
- package/runtime/memory/KeyMerger.ts +25 -23
- package/runtime/memory/MultiAddressMemoryMap.ts +11 -8
- package/runtime/memory/MultiStringMemoryMap.ts +8 -5
- package/runtime/memory/StringMemoryMap.ts +15 -15
- package/runtime/memory/Uint8ArrayMerger.ts +22 -15
- package/runtime/storage/Serializable.ts +19 -20
- package/runtime/storage/StoredAddress.ts +16 -15
- package/runtime/storage/StoredBoolean.ts +26 -21
- package/runtime/storage/StoredString.ts +158 -102
- package/runtime/storage/StoredU256.ts +25 -28
- package/runtime/storage/StoredU64.ts +23 -35
- package/runtime/storage/arrays/StoredAddressArray.ts +83 -175
- package/runtime/storage/arrays/StoredBooleanArray.ts +146 -271
- package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
- package/runtime/storage/arrays/StoredU128Array.ts +38 -374
- package/runtime/storage/arrays/StoredU16Array.ts +34 -420
- package/runtime/storage/arrays/StoredU256Array.ts +21 -347
- package/runtime/storage/arrays/StoredU32Array.ts +37 -440
- package/runtime/storage/arrays/StoredU64Array.ts +66 -0
- package/runtime/storage/arrays/StoredU8Array.ts +29 -453
- package/runtime/types/Address.ts +72 -5
- package/runtime/types/index.ts +1 -4
- package/runtime/utils/encodings.ts +5 -6
- package/runtime/utils/hex.ts +1 -1
- package/runtime/interfaces/DeployContractResponse.ts +0 -12
- package/runtime/math/cyrb53.ts +0 -48
- package/runtime/math/sha256.ts +0 -12
- package/runtime/memory/MemorySlot.ts +0 -1
- package/runtime/memory/MemorySlotPointer.ts +0 -3
- package/runtime/storage/utils/StorageBacked.ts +0 -5
- package/runtime/storage/utils/StorageLayout.ts +0 -7
- package/runtime/storage/utils/StorageSlot.ts +0 -106
- package/runtime/storage/utils/StorageStruct.ts +0 -23
- package/runtime/storage/utils/StorageValue.ts +0 -36
- package/runtime/tests/assert.ts +0 -11
- package/runtime/tests/env.ts +0 -7
- package/runtime/tests/tests.ts +0 -28
|
@@ -1,93 +1,82 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BytesReader } from '../../buffer/BytesReader';
|
|
2
2
|
import { BytesWriter } from '../../buffer/BytesWriter';
|
|
3
3
|
import { Blockchain } from '../../env';
|
|
4
|
+
import { addUint8ArraysBE, u64ToBE32Bytes } from '../../math/bytes';
|
|
4
5
|
import { Address } from '../../types/Address';
|
|
5
6
|
import { Revert } from '../../types/Revert';
|
|
6
|
-
import { SafeMath } from '../../types/SafeMath';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @class StoredAddressArray
|
|
10
10
|
* @description Manages an array of Address values across multiple storage slots.
|
|
11
|
-
* Each slot holds one Address (stored as
|
|
11
|
+
* Each slot holds one Address (stored as a raw Uint8Array in storage).
|
|
12
12
|
*/
|
|
13
13
|
@final
|
|
14
14
|
export class StoredAddressArray {
|
|
15
|
-
private readonly baseU256Pointer:
|
|
16
|
-
private readonly lengthPointer:
|
|
15
|
+
private readonly baseU256Pointer: Uint8Array;
|
|
16
|
+
private readonly lengthPointer: Uint8Array;
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
private _isLoaded: Set<u64> = new Set(); // Set of slotIndexes that are loaded
|
|
21
|
-
private _isChanged: Set<u64> = new Set(); // Set of slotIndexes that are modified
|
|
18
|
+
private _values: Map<u64, Address> = new Map(); // slotIndex -> Address
|
|
19
|
+
private _isChanged: Set<u64> = new Set(); // track changed slotIndexes
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private _isChangedStartIndex: bool = false; // Indicates if the startIndex has been modified
|
|
21
|
+
private _length: u64 = 0;
|
|
22
|
+
private _startIndex: u64 = 0;
|
|
23
|
+
private _isChangedLength: bool = false;
|
|
24
|
+
private _isChangedStartIndex: bool = false;
|
|
28
25
|
|
|
29
|
-
// Define a maximum allowed length to prevent excessive storage usage
|
|
30
26
|
private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
|
|
31
27
|
|
|
28
|
+
private readonly defaultValue: Address = Address.zero();
|
|
29
|
+
|
|
32
30
|
/**
|
|
33
31
|
* @constructor
|
|
34
32
|
* @param {u16} pointer - The primary pointer identifier.
|
|
35
33
|
* @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
|
|
36
|
-
* @param {Address} defaultValue - The default Address value if storage is uninitialized.
|
|
37
34
|
*/
|
|
38
|
-
constructor(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
constructor(public pointer: u16, public subPointer: Uint8Array) {
|
|
36
|
+
assert(
|
|
37
|
+
subPointer.length <= 30,
|
|
38
|
+
`You must pass a 30 bytes sub-pointer. (AddressArray, got ${subPointer.length})`,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Construct base pointer as a 32-byte array
|
|
44
42
|
const writer = new BytesWriter(32);
|
|
45
43
|
writer.writeU16(pointer);
|
|
46
44
|
writer.writeBytes(subPointer);
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
const
|
|
46
|
+
// We'll reuse the same bytes as the "base pointer" for offsets
|
|
47
|
+
const baseU256Pointer = writer.getBuffer(); // 32 bytes
|
|
48
|
+
// For length+startIndex, we'll use the same pointer
|
|
49
|
+
const lengthPointer = Uint8Array.wrap(baseU256Pointer.buffer);
|
|
50
|
+
|
|
51
|
+
// Load length + startIndex from storage (16 bytes: 8 for length, 8 for startIndex).
|
|
52
|
+
const storedLengthAndStartIndex: Uint8Array = Blockchain.getStorageAt(lengthPointer);
|
|
53
|
+
|
|
54
|
+
const reader = new BytesReader(storedLengthAndStartIndex);
|
|
55
|
+
this._length = reader.readU64();
|
|
56
|
+
this._startIndex = reader.readU64();
|
|
50
57
|
|
|
51
|
-
// Load the current length and startIndex from storage
|
|
52
|
-
const storedLengthAndStartIndex: u256 = Blockchain.getStorageAt(lengthPointer, u256.Zero);
|
|
53
58
|
this.lengthPointer = lengthPointer;
|
|
54
59
|
this.baseU256Pointer = baseU256Pointer;
|
|
55
|
-
|
|
56
|
-
this._length = storedLengthAndStartIndex.lo1; // Bytes 0-7: length
|
|
57
|
-
this._startIndex = storedLengthAndStartIndex.lo2; // Bytes 8-15: startIndex
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
/**
|
|
61
|
-
* @method get
|
|
62
|
-
* @description Retrieves the Address value at the specified global index.
|
|
63
|
-
* @param {u64} index - The global index of the Address to retrieve.
|
|
64
|
-
* @returns {Address} - The Address value at the specified index.
|
|
65
|
-
*/
|
|
62
|
+
/** Get an element by its global index. */
|
|
66
63
|
@inline
|
|
67
64
|
public get(index: u64): Address {
|
|
68
65
|
if (index > this.MAX_LENGTH) {
|
|
69
66
|
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
70
67
|
}
|
|
71
|
-
|
|
72
68
|
const slotIndex: u32 = <u32>index;
|
|
73
69
|
this.ensureValues(slotIndex);
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
return value ? value : this.defaultValue;
|
|
71
|
+
return this._values.get(slotIndex);
|
|
77
72
|
}
|
|
78
73
|
|
|
79
|
-
/**
|
|
80
|
-
* @method set
|
|
81
|
-
* @description Sets the Address value at the specified global index.
|
|
82
|
-
* @param {u64} index - The global index of the Address to set.
|
|
83
|
-
* @param {Address} value - The Address value to assign.
|
|
84
|
-
*/
|
|
74
|
+
/** Set an element by its global index. */
|
|
85
75
|
@inline
|
|
86
76
|
public set(index: u64, value: Address): void {
|
|
87
77
|
if (index > this.MAX_LENGTH) {
|
|
88
|
-
throw new Revert('Set
|
|
78
|
+
throw new Revert('Set failed: Index exceeds maximum allowed value.');
|
|
89
79
|
}
|
|
90
|
-
|
|
91
80
|
const slotIndex: u32 = <u32>index;
|
|
92
81
|
this.ensureValues(slotIndex);
|
|
93
82
|
|
|
@@ -98,44 +87,27 @@ export class StoredAddressArray {
|
|
|
98
87
|
}
|
|
99
88
|
}
|
|
100
89
|
|
|
101
|
-
/**
|
|
102
|
-
* @method indexOf
|
|
103
|
-
* @description Searches for the first occurrence of the specified Address value and returns its index.
|
|
104
|
-
* @param {Address} value - The Address to locate.
|
|
105
|
-
* @returns {i64} - The index of the first occurrence, or -1 if not found.
|
|
106
|
-
*/
|
|
90
|
+
/** Find the first index containing `value`. Returns -1 if not found. */
|
|
107
91
|
@inline
|
|
108
92
|
public indexOf(value: Address): i64 {
|
|
109
93
|
for (let i: u64 = 0; i < this._length; i++) {
|
|
110
|
-
|
|
111
|
-
if (currentValue == value) {
|
|
94
|
+
if (this.get(i) == value) {
|
|
112
95
|
return i64(i);
|
|
113
96
|
}
|
|
114
97
|
}
|
|
115
98
|
return -1;
|
|
116
99
|
}
|
|
117
100
|
|
|
118
|
-
/**
|
|
119
|
-
* @method contains
|
|
120
|
-
* @description Determines whether the array contains the specified Address value.
|
|
121
|
-
* @param {Address} value - The Address to locate.
|
|
122
|
-
* @returns {boolean} - True if found; otherwise, false.
|
|
123
|
-
*/
|
|
101
|
+
/** Check if the array contains `value`. */
|
|
124
102
|
@inline
|
|
125
103
|
public contains(value: Address): boolean {
|
|
126
104
|
return this.indexOf(value) !== -1;
|
|
127
105
|
}
|
|
128
106
|
|
|
129
|
-
/**
|
|
130
|
-
* @method push
|
|
131
|
-
* @description Appends a new Address value to the end of the array.
|
|
132
|
-
* @param {Address} value - The Address to append.
|
|
133
|
-
*/
|
|
107
|
+
/** Append an address at the end of the array. */
|
|
134
108
|
public push(value: Address): void {
|
|
135
|
-
if (this._length
|
|
136
|
-
throw new Revert(
|
|
137
|
-
'Push operation failed: Array has reached its maximum allowed length.',
|
|
138
|
-
);
|
|
109
|
+
if (this._length >= this.MAX_LENGTH) {
|
|
110
|
+
throw new Revert('Push failed: Array has reached its maximum length.');
|
|
139
111
|
}
|
|
140
112
|
|
|
141
113
|
const newIndex: u64 = this._length;
|
|
@@ -151,13 +123,10 @@ export class StoredAddressArray {
|
|
|
151
123
|
this._isChangedLength = true;
|
|
152
124
|
}
|
|
153
125
|
|
|
154
|
-
/**
|
|
155
|
-
* @method deleteLast
|
|
156
|
-
* @description Deletes the last element from the array.
|
|
157
|
-
*/
|
|
126
|
+
/** Delete the last element. */
|
|
158
127
|
public deleteLast(): void {
|
|
159
128
|
if (this._length === 0) {
|
|
160
|
-
throw new Revert('Delete
|
|
129
|
+
throw new Revert('Delete failed: Array is empty.');
|
|
161
130
|
}
|
|
162
131
|
|
|
163
132
|
const lastIndex: u64 = this._length - 1;
|
|
@@ -174,21 +143,13 @@ export class StoredAddressArray {
|
|
|
174
143
|
this._isChangedLength = true;
|
|
175
144
|
}
|
|
176
145
|
|
|
177
|
-
/**
|
|
178
|
-
* @method setStartingIndex
|
|
179
|
-
* @description Sets the starting index of the array.
|
|
180
|
-
* @param {u64} index - The new starting index.
|
|
181
|
-
*/
|
|
146
|
+
/** Adjust the starting index. */
|
|
182
147
|
public setStartingIndex(index: u64): void {
|
|
183
148
|
this._startIndex = index;
|
|
184
149
|
this._isChangedStartIndex = true;
|
|
185
150
|
}
|
|
186
151
|
|
|
187
|
-
/**
|
|
188
|
-
* @method delete
|
|
189
|
-
* @description Deletes the Address value at the specified index by setting it to defaultValue.
|
|
190
|
-
* @param {u64} index - The global index of the Address value to delete.
|
|
191
|
-
*/
|
|
152
|
+
/** Delete a specific element by setting it to `defaultValue`. */
|
|
192
153
|
public delete(index: u64): void {
|
|
193
154
|
if (index > this.MAX_LENGTH) {
|
|
194
155
|
throw new Revert('Operation failed: Index exceeds maximum allowed value.');
|
|
@@ -205,47 +166,46 @@ export class StoredAddressArray {
|
|
|
205
166
|
}
|
|
206
167
|
|
|
207
168
|
/**
|
|
208
|
-
*
|
|
209
|
-
*
|
|
169
|
+
* Persist changes to storage.
|
|
170
|
+
* - Store any changed slotIndex -> Address
|
|
171
|
+
* - Store updated length and startIndex if changed
|
|
210
172
|
*/
|
|
211
173
|
public save(): void {
|
|
212
|
-
// Save
|
|
174
|
+
// 1) Save changed slots
|
|
213
175
|
const changed = this._isChanged.values();
|
|
214
176
|
for (let i = 0; i < changed.length; i++) {
|
|
215
177
|
const slotIndex = changed[i];
|
|
216
178
|
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
179
|
+
|
|
217
180
|
const value = this._values.get(slotIndex);
|
|
218
|
-
Blockchain.setStorageAt(storagePointer,
|
|
181
|
+
Blockchain.setStorageAt(storagePointer, value);
|
|
219
182
|
}
|
|
220
183
|
this._isChanged.clear();
|
|
221
184
|
|
|
222
|
-
// Save length and startIndex if changed
|
|
185
|
+
// 2) Save length and startIndex if changed
|
|
223
186
|
if (this._isChangedLength || this._isChangedStartIndex) {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
187
|
+
const writer = new BytesWriter(16);
|
|
188
|
+
writer.writeU64(this._length);
|
|
189
|
+
writer.writeU64(this._startIndex);
|
|
190
|
+
|
|
191
|
+
Blockchain.setStorageAt(this.lengthPointer, writer.getBuffer());
|
|
228
192
|
this._isChangedLength = false;
|
|
229
193
|
this._isChangedStartIndex = false;
|
|
230
194
|
}
|
|
231
195
|
}
|
|
232
196
|
|
|
233
|
-
/**
|
|
234
|
-
* @method deleteAll
|
|
235
|
-
* @description Deletes the entire array and resets length and startIndex.
|
|
236
|
-
*/
|
|
197
|
+
/** Clear entire array content from storage, reset length and startIndex. */
|
|
237
198
|
public deleteAll(): void {
|
|
238
199
|
// Clear all loaded slots
|
|
239
200
|
const keys = this._values.keys();
|
|
240
201
|
for (let i = 0; i < keys.length; i++) {
|
|
241
202
|
const slotIndex = keys[i];
|
|
242
203
|
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
243
|
-
Blockchain.setStorageAt(storagePointer,
|
|
204
|
+
Blockchain.setStorageAt(storagePointer, this.defaultValue);
|
|
244
205
|
}
|
|
245
206
|
|
|
246
|
-
// Reset
|
|
247
|
-
|
|
248
|
-
Blockchain.setStorageAt(this.lengthPointer, zeroLengthAndStartIndex);
|
|
207
|
+
// Reset length and startIndex in storage
|
|
208
|
+
Blockchain.setStorageAt(this.lengthPointer, new Uint8Array(0)); // or a 16-byte zero array if preferred
|
|
249
209
|
this._length = 0;
|
|
250
210
|
this._startIndex = 0;
|
|
251
211
|
this._isChangedLength = false;
|
|
@@ -253,16 +213,10 @@ export class StoredAddressArray {
|
|
|
253
213
|
|
|
254
214
|
// Clear internal caches
|
|
255
215
|
this._values.clear();
|
|
256
|
-
this._isLoaded.clear();
|
|
257
216
|
this._isChanged.clear();
|
|
258
217
|
}
|
|
259
218
|
|
|
260
|
-
/**
|
|
261
|
-
* @method setMultiple
|
|
262
|
-
* @description Sets multiple Address values starting from a specific global index.
|
|
263
|
-
* @param {u32} startIndex - The starting global index.
|
|
264
|
-
* @param {Address[]} values - An array of Address values to set.
|
|
265
|
-
*/
|
|
219
|
+
/** Bulk-set multiple addresses starting at `startIndex`. */
|
|
266
220
|
@inline
|
|
267
221
|
public setMultiple(startIndex: u32, values: Address[]): void {
|
|
268
222
|
for (let i: u32 = 0; i < values.length; i++) {
|
|
@@ -270,31 +224,21 @@ export class StoredAddressArray {
|
|
|
270
224
|
}
|
|
271
225
|
}
|
|
272
226
|
|
|
273
|
-
/**
|
|
274
|
-
* @method getAll
|
|
275
|
-
* @description Retrieves a range of Address values.
|
|
276
|
-
* @param {u32} startIndex - The start index.
|
|
277
|
-
* @param {u32} count - The number of items to get.
|
|
278
|
-
* @returns {Address[]} - The requested Address values.
|
|
279
|
-
*/
|
|
227
|
+
/** Retrieve a batch of addresses (range). */
|
|
280
228
|
@inline
|
|
281
229
|
public getAll(startIndex: u32, count: u32): Address[] {
|
|
282
|
-
if (
|
|
230
|
+
if (startIndex + count > this._length) {
|
|
283
231
|
throw new Revert('Requested range exceeds array length');
|
|
284
232
|
}
|
|
285
233
|
|
|
286
|
-
const result
|
|
234
|
+
const result = new Array<Address>(count);
|
|
287
235
|
for (let i: u32 = 0; i < count; i++) {
|
|
288
236
|
result[i] = this.get(<u64>(startIndex + i));
|
|
289
237
|
}
|
|
290
238
|
return result;
|
|
291
239
|
}
|
|
292
240
|
|
|
293
|
-
/**
|
|
294
|
-
* @method toString
|
|
295
|
-
* @description Returns a string representation of the array.
|
|
296
|
-
* @returns {string} - A string of the form "[addr0, addr1, ...]".
|
|
297
|
-
*/
|
|
241
|
+
/** Returns a string of the form "[addr0, addr1, ...]". */
|
|
298
242
|
@inline
|
|
299
243
|
public toString(): string {
|
|
300
244
|
let str = '[';
|
|
@@ -309,31 +253,7 @@ export class StoredAddressArray {
|
|
|
309
253
|
return str;
|
|
310
254
|
}
|
|
311
255
|
|
|
312
|
-
/**
|
|
313
|
-
* @method toBytes
|
|
314
|
-
* @description Returns the packed Address values as a byte array.
|
|
315
|
-
* @returns {u8[]} - The packed byte array.
|
|
316
|
-
*/
|
|
317
|
-
@inline
|
|
318
|
-
public toBytes(): u8[] {
|
|
319
|
-
const bytes: u8[] = new Array<u8>();
|
|
320
|
-
for (let i: u32 = 0; i < this._length; i++) {
|
|
321
|
-
this.ensureValues(i);
|
|
322
|
-
const value = this._values.get(i);
|
|
323
|
-
if (value) {
|
|
324
|
-
const valueBytes = value; // Address is assumed to be or contain a Uint8Array
|
|
325
|
-
for (let j: u32 = 0; j < valueBytes.length; j++) {
|
|
326
|
-
bytes.push(valueBytes[j]);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return bytes;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* @method reset
|
|
335
|
-
* @description Resets the array by clearing all elements and resetting length and startIndex to zero.
|
|
336
|
-
*/
|
|
256
|
+
/** Reset in-memory and persist. */
|
|
337
257
|
@inline
|
|
338
258
|
public reset(): void {
|
|
339
259
|
this._length = 0;
|
|
@@ -343,53 +263,41 @@ export class StoredAddressArray {
|
|
|
343
263
|
this.save();
|
|
344
264
|
}
|
|
345
265
|
|
|
346
|
-
/**
|
|
347
|
-
* @method getLength
|
|
348
|
-
* @description Retrieves the current length of the array.
|
|
349
|
-
* @returns {u64} - The current length.
|
|
350
|
-
*/
|
|
266
|
+
/** Current array length. */
|
|
351
267
|
@inline
|
|
352
268
|
public getLength(): u64 {
|
|
353
269
|
return this._length;
|
|
354
270
|
}
|
|
355
271
|
|
|
356
|
-
/**
|
|
357
|
-
* @method startingIndex
|
|
358
|
-
* @description Retrieves the current starting index of the array.
|
|
359
|
-
* @returns {u64} - The starting index.
|
|
360
|
-
*/
|
|
272
|
+
/** Current starting index. */
|
|
361
273
|
public startingIndex(): u64 {
|
|
362
274
|
return this._startIndex;
|
|
363
275
|
}
|
|
364
276
|
|
|
365
277
|
/**
|
|
366
|
-
*
|
|
367
|
-
* @method ensureValues
|
|
368
|
-
* @description Loads and caches the Address from the specified storage slot if not already loaded.
|
|
369
|
-
* @param {u32} slotIndex - The index of the storage slot.
|
|
278
|
+
* Ensure the given slot index is loaded into `_values`.
|
|
370
279
|
*/
|
|
371
280
|
private ensureValues(slotIndex: u32): void {
|
|
372
|
-
if (!this.
|
|
281
|
+
if (!this._values.has(slotIndex)) {
|
|
373
282
|
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
374
|
-
|
|
283
|
+
|
|
284
|
+
// Load raw bytes from storage
|
|
285
|
+
const stored: Uint8Array = Blockchain.getStorageAt(storagePointer);
|
|
286
|
+
|
|
375
287
|
const storedAddress: Address =
|
|
376
|
-
|
|
288
|
+
stored.length == 0 ? this.defaultValue : Address.fromUint8Array(stored);
|
|
289
|
+
|
|
377
290
|
this._values.set(slotIndex, storedAddress);
|
|
378
|
-
this._isLoaded.add(slotIndex);
|
|
379
291
|
}
|
|
380
292
|
}
|
|
381
293
|
|
|
382
294
|
/**
|
|
383
|
-
*
|
|
384
|
-
* @method calculateStoragePointer
|
|
385
|
-
* @description Calculates the storage pointer for a given slot index.
|
|
386
|
-
* @param {u64} slotIndex - The index of the storage slot.
|
|
387
|
-
* @returns {u256} - The calculated storage pointer.
|
|
295
|
+
* Compute a 32-byte storage pointer = basePointer + (slotIndex + 1) big-endian.
|
|
388
296
|
*/
|
|
389
|
-
private calculateStoragePointer(slotIndex: u64):
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
return
|
|
297
|
+
private calculateStoragePointer(slotIndex: u64): Uint8Array {
|
|
298
|
+
// Convert (slotIndex + 1) to a 32-byte big-endian offset
|
|
299
|
+
const offset = u64ToBE32Bytes(slotIndex + 1);
|
|
300
|
+
|
|
301
|
+
return addUint8ArraysBE(this.baseU256Pointer, offset);
|
|
394
302
|
}
|
|
395
303
|
}
|