@btc-vision/btc-runtime 1.3.9 → 1.3.10
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 +1 -1
- package/runtime/contracts/DeployableOP_20.ts +0 -1
- package/runtime/env/BlockchainEnvironment.ts +17 -0
- package/runtime/env/global.ts +4 -0
- package/runtime/storage/StoredU128Array.ts +253 -88
- package/runtime/storage/StoredU16Array.ts +307 -116
- package/runtime/storage/StoredU256Array.ts +206 -124
|
@@ -1,136 +1,229 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { u256 } from 'as-bignum/assembly';
|
|
2
2
|
import { Blockchain } from '../env';
|
|
3
|
-
import { encodePointer } from '../math/abi';
|
|
4
3
|
import { BytesWriter } from '../buffer/BytesWriter';
|
|
5
|
-
import { u256 } from 'as-bignum/assembly';
|
|
6
4
|
import { SafeMath } from '../types/SafeMath';
|
|
5
|
+
import { Revert } from '../types/Revert';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* @class StoredU256Array
|
|
10
|
-
* @description Manages an array of u256 values across multiple
|
|
9
|
+
* @description Manages an array of u256 values across multiple storage slots. Each slot holds one u256 value.
|
|
11
10
|
*/
|
|
12
11
|
@final
|
|
13
12
|
export class StoredU256Array {
|
|
14
13
|
private readonly baseU256Pointer: u256;
|
|
15
14
|
private readonly lengthPointer: u256;
|
|
16
15
|
|
|
17
|
-
// Internal cache for
|
|
18
|
-
private _values:
|
|
19
|
-
private _isLoaded:
|
|
20
|
-
private _isChanged:
|
|
16
|
+
// Internal cache for storage slots
|
|
17
|
+
private _values: Map<u64, u256> = new Map(); // Map from slotIndex to u256 value
|
|
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
|
|
21
20
|
|
|
22
|
-
// Internal variables for length management
|
|
23
|
-
private _length:
|
|
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
24
|
private _isChangedLength: bool = false; // Indicates if the length has been modified
|
|
25
|
+
private _isChangedStartIndex: bool = false; // Indicates if the startIndex has been modified
|
|
26
|
+
|
|
27
|
+
// Define a maximum allowed length to prevent excessive storage usage
|
|
28
|
+
private readonly MAX_LENGTH: u64 = u64.MAX_VALUE - 1;
|
|
25
29
|
|
|
26
30
|
/**
|
|
27
31
|
* @constructor
|
|
28
32
|
* @param {u16} pointer - The primary pointer identifier.
|
|
29
|
-
* @param {
|
|
33
|
+
* @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
|
|
30
34
|
* @param {u256} defaultValue - The default u256 value if storage is uninitialized.
|
|
31
35
|
*/
|
|
32
36
|
constructor(
|
|
33
37
|
public pointer: u16,
|
|
34
|
-
public subPointer:
|
|
38
|
+
public subPointer: Uint8Array,
|
|
35
39
|
private defaultValue: u256,
|
|
36
40
|
) {
|
|
37
41
|
// Initialize the base u256 pointer using the primary pointer and subPointer
|
|
38
42
|
const writer = new BytesWriter(32);
|
|
39
|
-
writer.
|
|
40
|
-
|
|
43
|
+
writer.writeU16(pointer);
|
|
44
|
+
writer.writeBytes(subPointer);
|
|
41
45
|
|
|
42
|
-
// Initialize the
|
|
43
|
-
|
|
46
|
+
// Initialize the base and length pointers
|
|
47
|
+
const baseU256Pointer = u256.fromBytes(writer.getBuffer(), true);
|
|
48
|
+
const lengthPointer = baseU256Pointer.clone();
|
|
44
49
|
|
|
45
|
-
// Load the current length from storage
|
|
46
|
-
const
|
|
47
|
-
this.
|
|
50
|
+
// Load the current length and startIndex from storage
|
|
51
|
+
const storedLengthAndStartIndex: u256 = Blockchain.getStorageAt(lengthPointer, u256.Zero);
|
|
52
|
+
this.lengthPointer = lengthPointer;
|
|
53
|
+
this.baseU256Pointer = baseU256Pointer;
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.ensureValues(i);
|
|
52
|
-
}
|
|
55
|
+
this._length = storedLengthAndStartIndex.lo1; // Bytes 0-7: length
|
|
56
|
+
this._startIndex = storedLengthAndStartIndex.lo2; // Bytes 8-15: startIndex
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
/**
|
|
56
60
|
* @method get
|
|
57
61
|
* @description Retrieves the u256 value at the specified global index.
|
|
58
|
-
* @param {
|
|
62
|
+
* @param {u64} index - The global index (0 to ∞) of the u256 value to retrieve.
|
|
59
63
|
* @returns {u256} - The u256 value at the specified index.
|
|
60
64
|
*/
|
|
61
65
|
@inline
|
|
62
|
-
public get(index:
|
|
63
|
-
|
|
66
|
+
public get(index: u64): u256 {
|
|
67
|
+
assert(index < this._length, 'Index out of bounds');
|
|
68
|
+
const slotIndex: u32 = <u32>index;
|
|
64
69
|
this.ensureValues(slotIndex);
|
|
65
|
-
|
|
70
|
+
const value = this._values.get(slotIndex);
|
|
71
|
+
return value ? value : u256.Zero;
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
/**
|
|
69
75
|
* @method set
|
|
70
76
|
* @description Sets the u256 value at the specified global index.
|
|
71
|
-
* @param {
|
|
77
|
+
* @param {u64} index - The global index (0 to ∞) of the u256 value to set.
|
|
72
78
|
* @param {u256} value - The u256 value to assign.
|
|
73
79
|
*/
|
|
74
80
|
@inline
|
|
75
|
-
public set(index:
|
|
76
|
-
|
|
81
|
+
public set(index: u64, value: u256): void {
|
|
82
|
+
assert(index < this._length, 'Index exceeds current array length');
|
|
83
|
+
const slotIndex: u32 = <u32>index;
|
|
77
84
|
this.ensureValues(slotIndex);
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.
|
|
86
|
+
const currentValue = this._values.get(slotIndex);
|
|
87
|
+
if (!u256.eq(currentValue, value)) {
|
|
88
|
+
this._values.set(slotIndex, value);
|
|
89
|
+
this._isChanged.add(slotIndex);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
82
92
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
/**
|
|
94
|
+
* @method push
|
|
95
|
+
* @description Appends a new u256 value to the end of the array.
|
|
96
|
+
* @param {u256} value - The u256 value to append.
|
|
97
|
+
*/
|
|
98
|
+
public push(value: u256): void {
|
|
99
|
+
if (this._length >= this.MAX_LENGTH) {
|
|
100
|
+
throw new Revert(
|
|
101
|
+
'Push operation failed: Array has reached its maximum allowed length.',
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const newIndex: u64 = this._length;
|
|
106
|
+
const effectiveIndex: u64 = this._startIndex + newIndex;
|
|
107
|
+
const wrappedIndex: u64 =
|
|
108
|
+
effectiveIndex < this.MAX_LENGTH ? effectiveIndex : effectiveIndex % this.MAX_LENGTH;
|
|
109
|
+
const slotIndex: u32 = <u32>wrappedIndex;
|
|
110
|
+
|
|
111
|
+
// Ensure the slot is loaded
|
|
112
|
+
this.ensureValues(slotIndex);
|
|
113
|
+
|
|
114
|
+
// Set the new value
|
|
115
|
+
this._values.set(slotIndex, value);
|
|
116
|
+
this._isChanged.add(slotIndex);
|
|
117
|
+
|
|
118
|
+
// Increment the length
|
|
119
|
+
this._length += 1;
|
|
120
|
+
this._isChangedLength = true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @method delete
|
|
125
|
+
* @description Deletes the u256 value at the specified index by setting it to zero. Does not reorder the array.
|
|
126
|
+
* @param {u64} index - The global index of the u256 value to delete.
|
|
127
|
+
*/
|
|
128
|
+
public delete(index: u64): void {
|
|
129
|
+
if (index >= this._length) {
|
|
130
|
+
throw new Revert('Delete operation failed: Index out of bounds.');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const slotIndex: u32 = <u32>index;
|
|
134
|
+
this.ensureValues(slotIndex);
|
|
135
|
+
|
|
136
|
+
const currentValue = this._values.get(slotIndex);
|
|
137
|
+
if (!u256.eq(currentValue, u256.Zero)) {
|
|
138
|
+
this._values.set(slotIndex, u256.Zero);
|
|
139
|
+
this._isChanged.add(slotIndex);
|
|
88
140
|
}
|
|
89
141
|
}
|
|
90
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @method shift
|
|
145
|
+
* @description Removes the first element of the array by setting it to zero, decrementing the length, and incrementing the startIndex.
|
|
146
|
+
* If the startIndex reaches the maximum value of u64, it wraps around to 0.
|
|
147
|
+
*/
|
|
148
|
+
public shift(): void {
|
|
149
|
+
if (this._length === 0) {
|
|
150
|
+
throw new Revert('Shift operation failed: Array is empty.');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const currentStartIndex: u64 = this._startIndex;
|
|
154
|
+
const slotIndex: u32 = <u32>currentStartIndex;
|
|
155
|
+
this.ensureValues(slotIndex);
|
|
156
|
+
|
|
157
|
+
const currentValue = this._values.get(slotIndex);
|
|
158
|
+
if (!u256.eq(currentValue, u256.Zero)) {
|
|
159
|
+
this._values.set(slotIndex, u256.Zero);
|
|
160
|
+
this._isChanged.add(slotIndex);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Decrement the length
|
|
164
|
+
this._length -= 1;
|
|
165
|
+
this._isChangedLength = true;
|
|
166
|
+
|
|
167
|
+
// Increment the startIndex with wrap-around
|
|
168
|
+
if (this._startIndex < this.MAX_LENGTH - 1) {
|
|
169
|
+
this._startIndex += 1;
|
|
170
|
+
} else {
|
|
171
|
+
this._startIndex = 0;
|
|
172
|
+
}
|
|
173
|
+
this._isChangedStartIndex = true;
|
|
174
|
+
}
|
|
175
|
+
|
|
91
176
|
/**
|
|
92
177
|
* @method save
|
|
93
|
-
* @description Persists all cached u256 values and the
|
|
178
|
+
* @description Persists all cached u256 values, the length, and the startIndex to their respective storage slots if any have been modified.
|
|
94
179
|
*/
|
|
95
180
|
public save(): void {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
for (let
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this._isChanged[slotIndex] = false;
|
|
104
|
-
}
|
|
181
|
+
// Save all changed slots
|
|
182
|
+
const changed = this._isChanged.values();
|
|
183
|
+
for (let i = 0; i < changed.length; i++) {
|
|
184
|
+
const slotIndex = changed[i];
|
|
185
|
+
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
186
|
+
const value = this._values.get(slotIndex);
|
|
187
|
+
Blockchain.setStorageAt(storagePointer, value);
|
|
105
188
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
189
|
+
this._isChanged.clear();
|
|
190
|
+
|
|
191
|
+
// Save length and startIndex if changed
|
|
192
|
+
if (this._isChangedLength || this._isChangedStartIndex) {
|
|
193
|
+
const packedLengthAndStartIndex = new u256();
|
|
194
|
+
packedLengthAndStartIndex.lo1 = this._length;
|
|
195
|
+
packedLengthAndStartIndex.lo2 = this._startIndex;
|
|
196
|
+
Blockchain.setStorageAt(this.lengthPointer, packedLengthAndStartIndex);
|
|
110
197
|
this._isChangedLength = false;
|
|
198
|
+
this._isChangedStartIndex = false;
|
|
111
199
|
}
|
|
112
200
|
}
|
|
113
201
|
|
|
114
202
|
/**
|
|
115
|
-
* @method
|
|
116
|
-
* @description Deletes all storage slots by setting them to zero, including the length
|
|
203
|
+
* @method deleteAll
|
|
204
|
+
* @description Deletes all storage slots by setting them to zero, including the length and startIndex slots.
|
|
117
205
|
*/
|
|
118
|
-
public
|
|
119
|
-
|
|
120
|
-
|
|
206
|
+
public deleteAll(): void {
|
|
207
|
+
// Iterate over all loaded slots and clear them
|
|
208
|
+
const keys = this._values.keys();
|
|
209
|
+
for (let i = 0; i < keys.length; i++) {
|
|
210
|
+
const slotIndex = keys[i];
|
|
121
211
|
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
122
212
|
Blockchain.setStorageAt(storagePointer, u256.Zero);
|
|
123
213
|
}
|
|
124
214
|
|
|
125
|
-
// Reset the length to zero
|
|
126
|
-
|
|
215
|
+
// Reset the length and startIndex to zero
|
|
216
|
+
const zeroLengthAndStartIndex = u256.Zero;
|
|
217
|
+
Blockchain.setStorageAt(this.lengthPointer, zeroLengthAndStartIndex);
|
|
127
218
|
this._length = 0;
|
|
219
|
+
this._startIndex = 0;
|
|
128
220
|
this._isChangedLength = false;
|
|
221
|
+
this._isChangedStartIndex = false;
|
|
129
222
|
|
|
130
223
|
// Clear internal caches
|
|
131
|
-
this._values
|
|
132
|
-
this._isLoaded
|
|
133
|
-
this._isChanged
|
|
224
|
+
this._values.clear();
|
|
225
|
+
this._isLoaded.clear();
|
|
226
|
+
this._isChanged.clear();
|
|
134
227
|
}
|
|
135
228
|
|
|
136
229
|
/**
|
|
@@ -142,7 +235,7 @@ export class StoredU256Array {
|
|
|
142
235
|
@inline
|
|
143
236
|
public setMultiple(startIndex: u32, values: u256[]): void {
|
|
144
237
|
for (let i: u32 = 0; i < values.length; i++) {
|
|
145
|
-
this.set(startIndex + i, values[i]);
|
|
238
|
+
this.set(<u64>(startIndex + i), values[i]);
|
|
146
239
|
}
|
|
147
240
|
}
|
|
148
241
|
|
|
@@ -155,9 +248,10 @@ export class StoredU256Array {
|
|
|
155
248
|
*/
|
|
156
249
|
@inline
|
|
157
250
|
public getAll(startIndex: u32, count: u32): u256[] {
|
|
251
|
+
assert(startIndex + count <= this._length, 'Requested range exceeds array length');
|
|
158
252
|
const result: u256[] = new Array<u256>(count);
|
|
159
253
|
for (let i: u32 = 0; i < count; i++) {
|
|
160
|
-
result[i] = this.get(startIndex + i);
|
|
254
|
+
result[i] = this.get(<u64>(startIndex + i));
|
|
161
255
|
}
|
|
162
256
|
return result;
|
|
163
257
|
}
|
|
@@ -170,10 +264,10 @@ export class StoredU256Array {
|
|
|
170
264
|
@inline
|
|
171
265
|
public toString(): string {
|
|
172
266
|
let str = '[';
|
|
173
|
-
for (let
|
|
174
|
-
const value = this.
|
|
267
|
+
for (let i: u32 = 0; i < this._length; i++) {
|
|
268
|
+
const value = this.get(<u64>i);
|
|
175
269
|
str += value.toString();
|
|
176
|
-
if (
|
|
270
|
+
if (i !== this._length - 1) {
|
|
177
271
|
str += ', ';
|
|
178
272
|
}
|
|
179
273
|
}
|
|
@@ -189,11 +283,14 @@ export class StoredU256Array {
|
|
|
189
283
|
@inline
|
|
190
284
|
public toBytes(): u8[] {
|
|
191
285
|
const bytes: u8[] = new Array<u8>();
|
|
192
|
-
for (let
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
286
|
+
for (let i: u32 = 0; i < this._length; i++) {
|
|
287
|
+
this.ensureValues(i);
|
|
288
|
+
const value = this._values.get(i);
|
|
289
|
+
if (value) {
|
|
290
|
+
const valueBytes = value.toBytes();
|
|
291
|
+
for (let j: u32 = 0; j < valueBytes.length; j++) {
|
|
292
|
+
bytes.push(valueBytes[j]);
|
|
293
|
+
}
|
|
197
294
|
}
|
|
198
295
|
}
|
|
199
296
|
return bytes;
|
|
@@ -201,38 +298,53 @@ export class StoredU256Array {
|
|
|
201
298
|
|
|
202
299
|
/**
|
|
203
300
|
* @method reset
|
|
204
|
-
* @description Resets all cached u256 values to zero and marks them as changed, including resetting the length.
|
|
301
|
+
* @description Resets all cached u256 values to zero and marks them as changed, including resetting the length and startIndex.
|
|
205
302
|
*/
|
|
206
303
|
@inline
|
|
207
304
|
public reset(): void {
|
|
208
|
-
|
|
209
|
-
this._values[slotIndex] = u256.Zero;
|
|
210
|
-
this._isChanged[slotIndex] = true;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Reset the length to zero
|
|
305
|
+
// Reset the length and startIndex to zero
|
|
214
306
|
this._length = 0;
|
|
307
|
+
this._startIndex = 0;
|
|
215
308
|
this._isChangedLength = true;
|
|
309
|
+
this._isChangedStartIndex = true;
|
|
310
|
+
|
|
311
|
+
this.save();
|
|
216
312
|
}
|
|
217
313
|
|
|
218
314
|
/**
|
|
219
315
|
* @method getLength
|
|
220
316
|
* @description Retrieves the current length of the array.
|
|
221
|
-
* @returns {
|
|
317
|
+
* @returns {u64} - The current length.
|
|
222
318
|
*/
|
|
223
319
|
@inline
|
|
224
|
-
public getLength():
|
|
320
|
+
public getLength(): u64 {
|
|
225
321
|
return this._length;
|
|
226
322
|
}
|
|
227
323
|
|
|
324
|
+
/**
|
|
325
|
+
* @method startingIndex
|
|
326
|
+
* @description Retrieves the current starting index of the array.
|
|
327
|
+
* @returns {u64} - The starting index.
|
|
328
|
+
*/
|
|
329
|
+
public startingIndex(): u64 {
|
|
330
|
+
return this._startIndex;
|
|
331
|
+
}
|
|
332
|
+
|
|
228
333
|
/**
|
|
229
334
|
* @method setLength
|
|
230
335
|
* @description Sets the length of the array.
|
|
231
|
-
* @param {
|
|
336
|
+
* @param {u64} newLength - The new length to set.
|
|
232
337
|
*/
|
|
233
|
-
public setLength(newLength:
|
|
234
|
-
if (newLength >
|
|
235
|
-
throw new
|
|
338
|
+
public setLength(newLength: u64): void {
|
|
339
|
+
if (newLength > this.MAX_LENGTH) {
|
|
340
|
+
throw new Revert('SetLength operation failed: Length exceeds maximum allowed value.');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (newLength < this._length) {
|
|
344
|
+
// Truncate the array if newLength is smaller
|
|
345
|
+
for (let i: u64 = newLength; i < this._length; i++) {
|
|
346
|
+
this.delete(i);
|
|
347
|
+
}
|
|
236
348
|
}
|
|
237
349
|
|
|
238
350
|
this._length = newLength;
|
|
@@ -246,55 +358,25 @@ export class StoredU256Array {
|
|
|
246
358
|
* @param {u32} slotIndex - The index of the storage slot.
|
|
247
359
|
*/
|
|
248
360
|
private ensureValues(slotIndex: u32): void {
|
|
249
|
-
|
|
250
|
-
while (slotIndex >= <u32>this._isLoaded.length) {
|
|
251
|
-
this._isLoaded.push(false);
|
|
252
|
-
this._isChanged.push(false);
|
|
253
|
-
this._values.push(u256.Zero);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (!this._isLoaded[slotIndex]) {
|
|
361
|
+
if (!this._isLoaded.has(slotIndex)) {
|
|
257
362
|
const storagePointer = this.calculateStoragePointer(slotIndex);
|
|
258
363
|
const storedU256: u256 = Blockchain.getStorageAt(storagePointer, this.defaultValue);
|
|
259
|
-
this._values
|
|
260
|
-
this._isLoaded
|
|
364
|
+
this._values.set(slotIndex, storedU256);
|
|
365
|
+
this._isLoaded.add(slotIndex);
|
|
261
366
|
}
|
|
262
367
|
}
|
|
263
368
|
|
|
264
|
-
/**
|
|
265
|
-
* @private
|
|
266
|
-
* @method packValues
|
|
267
|
-
* @description Retrieves the cached u256 value for storage.
|
|
268
|
-
* @param {u32} slotIndex - The index of the storage slot.
|
|
269
|
-
* @returns {u256} - The packed u256 value.
|
|
270
|
-
*/
|
|
271
|
-
private packValues(slotIndex: u32): u256 {
|
|
272
|
-
return this._values[slotIndex];
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* @private
|
|
277
|
-
* @method unpackU256
|
|
278
|
-
* @description Returns the u256 value as is since no unpacking is required.
|
|
279
|
-
* @param {u256} storedU256 - The u256 value to unpack.
|
|
280
|
-
* @returns {u256} - The unpacked u256 value.
|
|
281
|
-
*/
|
|
282
|
-
private unpackU256(storedU256: u256): u256 {
|
|
283
|
-
return storedU256;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
369
|
/**
|
|
287
370
|
* @private
|
|
288
371
|
* @method calculateStoragePointer
|
|
289
|
-
* @description Calculates the storage pointer for a given slot index by incrementing the
|
|
372
|
+
* @description Calculates the storage pointer for a given slot index by incrementing the base pointer.
|
|
290
373
|
* @param {u32} slotIndex - The index of the storage slot.
|
|
291
374
|
* @returns {u256} - The calculated storage pointer.
|
|
292
375
|
*/
|
|
293
|
-
private calculateStoragePointer(slotIndex:
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return SafeMath.add(modifiedSubPointer, u256.fromU32(slotIndex));
|
|
376
|
+
private calculateStoragePointer(slotIndex: u64): u256 {
|
|
377
|
+
// Each slot is identified by baseU256Pointer + slotIndex + 1
|
|
378
|
+
// Slot 0: baseU256Pointer + 1 (first element)
|
|
379
|
+
// Slot 1: baseU256Pointer + 2, etc.
|
|
380
|
+
return SafeMath.add(this.baseU256Pointer, u256.fromU64(slotIndex + 1));
|
|
299
381
|
}
|
|
300
382
|
}
|