@btc-vision/btc-runtime 1.3.14 → 1.3.16

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 (49) hide show
  1. package/package.json +2 -2
  2. package/runtime/buffer/BytesReader.ts +1 -1
  3. package/runtime/buffer/BytesWriter.ts +1 -1
  4. package/runtime/contracts/DeployableOP_20.ts +1 -1
  5. package/runtime/contracts/OP_20.ts +1 -1
  6. package/runtime/contracts/interfaces/OP20InitParameters.ts +1 -1
  7. package/runtime/env/BlockchainEnvironment.ts +7 -7
  8. package/runtime/env/classes/Block.ts +1 -1
  9. package/runtime/events/predefined/ApproveEvent.ts +1 -1
  10. package/runtime/events/predefined/BurnEvent.ts +1 -1
  11. package/runtime/events/predefined/ClaimEvent.ts +1 -1
  12. package/runtime/events/predefined/MintEvent.ts +1 -1
  13. package/runtime/events/predefined/StakeEvent.ts +1 -1
  14. package/runtime/events/predefined/TransferEvent.ts +1 -1
  15. package/runtime/events/predefined/UnstakeEvent.ts +1 -1
  16. package/runtime/generic/MapU256.ts +1 -1
  17. package/runtime/index.ts +1 -0
  18. package/runtime/interfaces/DeployContractResponse.ts +1 -1
  19. package/runtime/math/bytes.ts +1 -1
  20. package/runtime/math/i256.ts +1 -1
  21. package/runtime/math/u160.ts +1 -1
  22. package/runtime/memory/AddressMemoryMap.ts +1 -1
  23. package/runtime/memory/KeyMerger.ts +1 -1
  24. package/runtime/memory/MemorySlotPointer.ts +1 -1
  25. package/runtime/memory/MultiAddressMemoryMap.ts +1 -1
  26. package/runtime/memory/MultiStringMemoryMap.ts +1 -1
  27. package/runtime/memory/StringMemoryMap.ts +1 -1
  28. package/runtime/memory/Uint8ArrayMerger.ts +1 -1
  29. package/runtime/secp256k1/ECPoint.ts +1 -1
  30. package/runtime/shared-libraries/OP20Utils.ts +1 -1
  31. package/runtime/shared-libraries/TransferHelper.ts +1 -1
  32. package/runtime/storage/Serializable.ts +1 -1
  33. package/runtime/storage/StorageBacked.ts +1 -1
  34. package/runtime/storage/StorageSlot.ts +1 -1
  35. package/runtime/storage/StorageValue.ts +1 -1
  36. package/runtime/storage/StoredAddress.ts +1 -1
  37. package/runtime/storage/StoredAddressArray.ts +437 -0
  38. package/runtime/storage/StoredBoolean.ts +1 -1
  39. package/runtime/storage/StoredBooleanArray.ts +1 -1
  40. package/runtime/storage/StoredString.ts +1 -1
  41. package/runtime/storage/StoredU128Array.ts +2 -3
  42. package/runtime/storage/StoredU16Array.ts +3 -3
  43. package/runtime/storage/StoredU256.ts +1 -1
  44. package/runtime/storage/StoredU256Array.ts +2 -3
  45. package/runtime/storage/StoredU64.ts +1 -1
  46. package/runtime/tests/tests.ts +1 -1
  47. package/runtime/types/SafeMath.ts +76 -25
  48. package/runtime/types/index.ts +1 -1
  49. package/runtime/utils/encodings.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "scripts": {
@@ -43,8 +43,8 @@
43
43
  ],
44
44
  "dependencies": {
45
45
  "@assemblyscript/loader": "^0.27.30",
46
+ "@btc-vision/as-bignum": "^0.0.2",
46
47
  "@eslint/js": "^9.10.0",
47
- "as-bignum": "^0.3.1",
48
48
  "gulplog": "^2.2.0",
49
49
  "mocha": "^10.7.3",
50
50
  "ts-node": "^10.9.2",
@@ -1,6 +1,6 @@
1
1
  import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
2
2
  import { Selector } from '../math/abi';
3
- import { i128, u128, u256 } from 'as-bignum/assembly';
3
+ import { i128, u128, u256 } from '@btc-vision/as-bignum/assembly';
4
4
  import { Revert } from '../types/Revert';
5
5
  import { TransactionInput, TransactionOutput } from '../env/classes/UTXO';
6
6
  import { i256 } from '../math/i256';
@@ -1,4 +1,4 @@
1
- import { i128, u128, u256 } from 'as-bignum/assembly';
1
+ import { i128, u128, u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
3
3
  import { Selector } from '../math/abi';
4
4
  import { BytesReader } from './BytesReader';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { BytesWriter } from '../buffer/BytesWriter';
3
3
  import { Blockchain } from '../env';
4
4
  import { ApproveEvent, BurnEvent, MintEvent, TransferEvent } from '../events/predefined';
@@ -1,5 +1,5 @@
1
1
  import { DeployableOP_20 } from './DeployableOP_20';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { OP20InitParameters } from './interfaces/OP20InitParameters';
4
4
 
5
5
  export abstract class OP_20 extends DeployableOP_20 {
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  export class OP20InitParameters {
4
4
  readonly maxSupply: u256;
@@ -1,7 +1,7 @@
1
1
  import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
2
2
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
3
3
  import { MemorySlotData } from '../memory/MemorySlot';
4
- import { u256 } from 'as-bignum/assembly';
4
+ import { u256 } from '@btc-vision/as-bignum/assembly';
5
5
  import { BytesReader } from '../buffer/BytesReader';
6
6
  import { BytesWriter } from '../buffer/BytesWriter';
7
7
  import { NetEvent } from '../events/NetEvent';
@@ -10,13 +10,11 @@ import { OP_NET } from '../contracts/OP_NET';
10
10
  import { PointerStorage } from '../types';
11
11
  import {
12
12
  callContract,
13
- deploy,
14
13
  deployFromAddress,
15
14
  emit,
16
15
  encodeAddress,
17
16
  loadPointer,
18
17
  log,
19
- nextPointerGreaterThan,
20
18
  storePointer,
21
19
  validateBitcoinAddress,
22
20
  verifySchnorrSignature,
@@ -186,7 +184,7 @@ export class BlockchainEnvironment {
186
184
  return reader.readAddress();
187
185
  }
188
186
 
189
- public deployContract(hash: u256, bytecode: Uint8Array): DeployContractResponse {
187
+ /*public deployContract(hash: u256, bytecode: Uint8Array): DeployContractResponse {
190
188
  const writer = new BytesWriter(32 + bytecode.length);
191
189
  writer.writeU256(hash);
192
190
  writer.writeBytes(bytecode);
@@ -199,7 +197,7 @@ export class BlockchainEnvironment {
199
197
  const contractAddress: Address = reader.readAddress();
200
198
 
201
199
  return new DeployContractResponse(virtualAddress, contractAddress);
202
- }
200
+ }*/
203
201
 
204
202
  public deployContractFromExisting(
205
203
  existingAddress: Address,
@@ -220,6 +218,7 @@ export class BlockchainEnvironment {
220
218
  return new DeployContractResponse(virtualAddress, contractAddress);
221
219
  }
222
220
 
221
+ // TODO: Change MemorySlotData type to a Uint8Array instead of a u256.
223
222
  public getStorageAt(
224
223
  pointerHash: MemorySlotPointer,
225
224
  defaultValue: MemorySlotData<u256>,
@@ -233,7 +232,7 @@ export class BlockchainEnvironment {
233
232
  return defaultValue;
234
233
  }
235
234
 
236
- public getNextPointerGreaterThan(
235
+ /*public getNextPointerGreaterThan(
237
236
  targetPointer: MemorySlotPointer,
238
237
  valueAtLeast: u256,
239
238
  lte: boolean = true,
@@ -247,7 +246,7 @@ export class BlockchainEnvironment {
247
246
  const reader: BytesReader = new BytesReader(result);
248
247
 
249
248
  return reader.readU256();
250
- }
249
+ }*/
251
250
 
252
251
  public verifySchnorrSignature(
253
252
  publicKey: Address,
@@ -265,6 +264,7 @@ export class BlockchainEnvironment {
265
264
  return reader.readBoolean();
266
265
  }
267
266
 
267
+ // TODO: Change MemorySlotData type to a Uint8Array instead of a u256.
268
268
  public hasStorageAt(pointerHash: MemorySlotPointer): bool {
269
269
  // We mark zero as the default value for the storage, if something is 0, the storage slot get deleted or is non-existent
270
270
  const val: u256 = this.getStorageAt(pointerHash, u256.Zero);
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  @final
4
4
  export class Block {
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Address, ADDRESS_BYTE_LENGTH } from '../../types/Address';
3
3
  import { NetEvent } from '../NetEvent';
4
4
  import { BytesWriter } from '../../buffer/BytesWriter';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { BytesWriter } from '../../buffer/BytesWriter';
4
4
 
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { BytesWriter } from '../../buffer/BytesWriter';
4
4
 
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { BytesWriter } from '../../buffer/BytesWriter';
4
4
  import { Address, ADDRESS_BYTE_LENGTH } from '../../types/Address';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { BytesWriter } from '../../buffer/BytesWriter';
4
4
 
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { Address, ADDRESS_BYTE_LENGTH } from '../../types/Address';
4
4
  import { BytesWriter } from '../../buffer/BytesWriter';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { BytesWriter } from '../../buffer/BytesWriter';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { Revert } from '../types/Revert';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { Map } from './Map';
4
4
 
5
5
  export class MapU256 extends Map<u256, u256> {
package/runtime/index.ts CHANGED
@@ -70,6 +70,7 @@ export * from './storage/StoredString';
70
70
  export * from './storage/StoredAddress';
71
71
  export * from './storage/StoredBoolean';
72
72
  export * from './storage/Serializable';
73
+ export * from './storage/StoredAddressArray';
73
74
 
74
75
  export * from './storage/StorageBacked';
75
76
  export * from './storage/StorageSlot';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Address } from '../types/Address';
3
3
 
4
4
  export class DeployContractResponse {
@@ -1,4 +1,4 @@
1
- import { u128, u256 } from 'as-bignum/assembly';
1
+ import { u128, u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  export function bytes(number: u256[]): Uint8Array {
4
4
  const result = new Uint8Array(32 * number.length);
@@ -1,4 +1,4 @@
1
- import { i128, u128, u256 } from 'as-bignum/assembly';
1
+ import { i128, u128, u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  export class i256 {
4
4
 
@@ -1,4 +1,4 @@
1
- import { i128, u128 } from 'as-bignum/assembly';
1
+ import { i128, u128 } from '@btc-vision/as-bignum/assembly';
2
2
  import { __carry, __uadd64, __umulh64 } from 'as-bignum/assembly/globals';
3
3
 
4
4
  @lazy const HEX_CHARS = '0123456789abcdef';
@@ -2,7 +2,7 @@ import { MemorySlotPointer } from './MemorySlotPointer';
2
2
  import { Blockchain } from '../env';
3
3
  import { encodePointer } from '../math/abi';
4
4
  import { MemorySlotData } from './MemorySlot';
5
- import { u256 } from 'as-bignum/assembly';
5
+ import { u256 } from '@btc-vision/as-bignum/assembly';
6
6
  import { BytesWriter } from '../buffer/BytesWriter';
7
7
  import { Address } from '../types/Address';
8
8
 
@@ -1,5 +1,5 @@
1
1
  import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { Blockchain } from '../env';
4
4
  import { MemorySlotPointer } from './MemorySlotPointer';
5
5
  import { encodePointer } from '../math/abi';
@@ -1,3 +1,3 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  export type MemorySlotPointer = u256;
@@ -1,5 +1,5 @@
1
1
  import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { Uint8ArrayMerger } from './Uint8ArrayMerger';
4
4
  import { Address } from '../types/Address';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { KeyMerger } from './KeyMerger';
4
4
 
5
5
  @final
@@ -2,7 +2,7 @@ import { MemorySlotPointer } from './MemorySlotPointer';
2
2
  import { Blockchain } from '../env';
3
3
  import { encodePointer } from '../math/abi';
4
4
  import { MemorySlotData } from './MemorySlot';
5
- import { u256 } from 'as-bignum/assembly';
5
+ import { u256 } from '@btc-vision/as-bignum/assembly';
6
6
  import { BytesWriter } from '../buffer/BytesWriter';
7
7
 
8
8
  @final
@@ -1,5 +1,5 @@
1
1
  import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { Blockchain } from '../env';
4
4
  import { MemorySlotPointer } from './MemorySlotPointer';
5
5
  import { encodePointer } from '../math/abi';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { SafeMath } from '../types/SafeMath';
3
3
 
4
4
  // secp256k1 curve parameters (using little-endian byte arrays)
@@ -1,5 +1,5 @@
1
1
  import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
2
- import { u256 } from 'as-bignum/assembly';
2
+ import { u256 } from '@btc-vision/as-bignum/assembly';
3
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
4
  import { Blockchain } from '../env';
5
5
  import { encodeSelector, Selector } from '../math/abi';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { encodeSelector, Selector } from '../math/abi';
3
3
  import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
4
4
  import { BytesWriter } from '../buffer/BytesWriter';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
4
4
  import { BytesWriter } from '../buffer/BytesWriter';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  export interface StorageBacked {
4
4
  serialize(): Array<u256>;
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { BlockchainEnvironment } from '../env/BlockchainEnvironment';
3
3
  import { Sha256 } from '../math/sha256';
4
4
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { StorageSlot } from './StorageSlot';
3
3
 
4
4
  export class StorageValue<T> {
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { encodePointer } from '../math/abi';
4
4
  import { BytesWriter } from '../buffer/BytesWriter';
@@ -0,0 +1,437 @@
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 { Address } from '../types/Address';
6
+ import { Revert } from '../types/Revert';
7
+
8
+ /**
9
+ * @class StoredAddressArray
10
+ * @description Manages an array of Address values across multiple storage slots.
11
+ * Each slot holds one Address (stored as u256 in storage).
12
+ */
13
+ @final
14
+ export class StoredAddressArray {
15
+ private readonly baseU256Pointer: u256;
16
+ private readonly lengthPointer: u256;
17
+
18
+ // Internal cache for storage slots
19
+ private _values: Map<u64, Address> = new Map(); // Map from slotIndex to Address value
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
22
+
23
+ // Internal variables for length and startIndex management
24
+ private _length: u64 = 0; // Current length of the array
25
+ private _startIndex: u64 = 0; // Starting index of the array
26
+ private _isChangedLength: bool = false; // Indicates if the length has been modified
27
+ private _isChangedStartIndex: bool = false; // Indicates if the startIndex has been modified
28
+
29
+ // Define a maximum allowed length to prevent excessive storage usage
30
+ private readonly MAX_LENGTH: u64 = u64(u32.MAX_VALUE - 1);
31
+
32
+ /**
33
+ * @constructor
34
+ * @param {u16} pointer - The primary pointer identifier.
35
+ * @param {Uint8Array} subPointer - The sub-pointer for memory slot addressing.
36
+ * @param {Address} defaultValue - The default Address value if storage is uninitialized.
37
+ */
38
+ constructor(
39
+ public pointer: u16,
40
+ public subPointer: Uint8Array,
41
+ private defaultValue: Address,
42
+ ) {
43
+ // Initialize the base pointer
44
+ const writer = new BytesWriter(32);
45
+ writer.writeU16(pointer);
46
+ writer.writeBytes(subPointer);
47
+
48
+ const baseU256Pointer = u256.fromBytes(writer.getBuffer(), true);
49
+ const lengthPointer = baseU256Pointer.clone();
50
+
51
+ // Load the current length and startIndex from storage
52
+ const storedLengthAndStartIndex: u256 = Blockchain.getStorageAt(lengthPointer, u256.Zero);
53
+ this.lengthPointer = lengthPointer;
54
+ this.baseU256Pointer = baseU256Pointer;
55
+
56
+ this._length = storedLengthAndStartIndex.lo1; // Bytes 0-7: length
57
+ this._startIndex = storedLengthAndStartIndex.lo2; // Bytes 8-15: startIndex
58
+ }
59
+
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
+ */
66
+ @inline
67
+ public get(index: u64): Address {
68
+ assert(index < this._length, 'Index out of bounds');
69
+ const slotIndex: u32 = <u32>index;
70
+ this.ensureValues(slotIndex);
71
+ const value = this._values.get(slotIndex);
72
+ return value ? value : this.defaultValue;
73
+ }
74
+
75
+ /**
76
+ * @method set
77
+ * @description Sets the Address value at the specified global index.
78
+ * @param {u64} index - The global index of the Address to set.
79
+ * @param {Address} value - The Address value to assign.
80
+ */
81
+ @inline
82
+ public set(index: u64, value: Address): void {
83
+ assert(index < this._length, 'Index exceeds current array length');
84
+ const slotIndex: u32 = <u32>index;
85
+ this.ensureValues(slotIndex);
86
+
87
+ const currentValue = this._values.get(slotIndex);
88
+ if (currentValue != value) {
89
+ this._values.set(slotIndex, value);
90
+ this._isChanged.add(slotIndex);
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @method indexOf
96
+ * @description Searches for the first occurrence of the specified Address value and returns its index.
97
+ * @param {Address} value - The Address to locate.
98
+ * @returns {i64} - The index of the first occurrence, or -1 if not found.
99
+ */
100
+ @inline
101
+ public indexOf(value: Address): i64 {
102
+ for (let i: u64 = 0; i < this._length; i++) {
103
+ const currentValue = this.get(i);
104
+ if (currentValue == value) {
105
+ return i64(i);
106
+ }
107
+ }
108
+ return -1;
109
+ }
110
+
111
+ /**
112
+ * @method contains
113
+ * @description Determines whether the array contains the specified Address value.
114
+ * @param {Address} value - The Address to locate.
115
+ * @returns {boolean} - True if found; otherwise, false.
116
+ */
117
+ @inline
118
+ public contains(value: Address): boolean {
119
+ return this.indexOf(value) !== -1;
120
+ }
121
+
122
+ /**
123
+ * @method push
124
+ * @description Appends a new Address value to the end of the array.
125
+ * @param {Address} value - The Address to append.
126
+ */
127
+ public push(value: Address): void {
128
+ if (this._length >= this.MAX_LENGTH) {
129
+ throw new Revert(
130
+ 'Push operation failed: Array has reached its maximum allowed length.',
131
+ );
132
+ }
133
+
134
+ const newIndex: u64 = this._length;
135
+ const wrappedIndex: u64 =
136
+ newIndex < this.MAX_LENGTH ? newIndex : newIndex % this.MAX_LENGTH;
137
+ const slotIndex: u32 = <u32>wrappedIndex;
138
+
139
+ this.ensureValues(slotIndex);
140
+ this._values.set(slotIndex, value);
141
+ this._isChanged.add(slotIndex);
142
+
143
+ this._length += 1;
144
+ this._isChangedLength = true;
145
+ }
146
+
147
+ /**
148
+ * @method deleteLast
149
+ * @description Deletes the last element from the array.
150
+ */
151
+ public deleteLast(): void {
152
+ if (this._length === 0) {
153
+ throw new Revert('Delete operation failed: Array is empty.');
154
+ }
155
+
156
+ const lastIndex: u64 = this._length - 1;
157
+ const slotIndex: u32 = <u32>(this._startIndex + lastIndex);
158
+ this.ensureValues(slotIndex);
159
+
160
+ const currentValue = this._values.get(slotIndex);
161
+ if (currentValue != this.defaultValue) {
162
+ this._values.set(slotIndex, this.defaultValue);
163
+ this._isChanged.add(slotIndex);
164
+ }
165
+
166
+ this._length -= 1;
167
+ this._isChangedLength = true;
168
+ }
169
+
170
+ /**
171
+ * @method setStartingIndex
172
+ * @description Sets the starting index of the array.
173
+ * @param {u64} index - The new starting index.
174
+ */
175
+ public setStartingIndex(index: u64): void {
176
+ this._startIndex = index;
177
+ this._isChangedStartIndex = true;
178
+ }
179
+
180
+ /**
181
+ * @method delete
182
+ * @description Deletes the Address value at the specified index by setting it to defaultValue.
183
+ * @param {u64} index - The global index of the Address value to delete.
184
+ */
185
+ public delete(index: u64): void {
186
+ if (index >= this._length) {
187
+ throw new Revert('Delete operation failed: Index out of bounds.');
188
+ }
189
+
190
+ const slotIndex: u32 = <u32>index;
191
+ this.ensureValues(slotIndex);
192
+
193
+ const currentValue = this._values.get(slotIndex);
194
+ if (currentValue != this.defaultValue) {
195
+ this._values.set(slotIndex, this.defaultValue);
196
+ this._isChanged.add(slotIndex);
197
+ }
198
+ }
199
+
200
+ /**
201
+ * @method shift
202
+ * @description Removes the first element of the array.
203
+ */
204
+ public shift(): void {
205
+ if (this._length === 0) {
206
+ throw new Revert('Shift operation failed: Array is empty.');
207
+ }
208
+
209
+ const currentStartIndex: u64 = this._startIndex;
210
+ const slotIndex: u32 = <u32>currentStartIndex;
211
+ this.ensureValues(slotIndex);
212
+
213
+ const currentValue = this._values.get(slotIndex);
214
+ if (currentValue != this.defaultValue) {
215
+ this._values.set(slotIndex, this.defaultValue);
216
+ this._isChanged.add(slotIndex);
217
+ }
218
+
219
+ this._length -= 1;
220
+ this._isChangedLength = true;
221
+
222
+ // Increment the startIndex with wrap-around
223
+ if (this._startIndex < this.MAX_LENGTH - 1) {
224
+ this._startIndex += 1;
225
+ } else {
226
+ this._startIndex = 0;
227
+ }
228
+ this._isChangedStartIndex = true;
229
+ }
230
+
231
+ /**
232
+ * @method save
233
+ * @description Persists all changes to storage.
234
+ */
235
+ public save(): void {
236
+ // Save all changed slots
237
+ const changed = this._isChanged.values();
238
+ for (let i = 0; i < changed.length; i++) {
239
+ const slotIndex = changed[i];
240
+ const storagePointer = this.calculateStoragePointer(slotIndex);
241
+ const value = this._values.get(slotIndex);
242
+ Blockchain.setStorageAt(storagePointer, u256.fromBytes(value));
243
+ }
244
+ this._isChanged.clear();
245
+
246
+ // Save length and startIndex if changed
247
+ if (this._isChangedLength || this._isChangedStartIndex) {
248
+ const packedLengthAndStartIndex = new u256();
249
+ packedLengthAndStartIndex.lo1 = this._length;
250
+ packedLengthAndStartIndex.lo2 = this._startIndex;
251
+ Blockchain.setStorageAt(this.lengthPointer, packedLengthAndStartIndex);
252
+ this._isChangedLength = false;
253
+ this._isChangedStartIndex = false;
254
+ }
255
+ }
256
+
257
+ /**
258
+ * @method deleteAll
259
+ * @description Deletes the entire array and resets length and startIndex.
260
+ */
261
+ public deleteAll(): void {
262
+ // Clear all loaded slots
263
+ const keys = this._values.keys();
264
+ for (let i = 0; i < keys.length; i++) {
265
+ const slotIndex = keys[i];
266
+ const storagePointer = this.calculateStoragePointer(slotIndex);
267
+ Blockchain.setStorageAt(storagePointer, u256.fromBytes(this.defaultValue));
268
+ }
269
+
270
+ // Reset the length and startIndex
271
+ const zeroLengthAndStartIndex = u256.Zero;
272
+ Blockchain.setStorageAt(this.lengthPointer, zeroLengthAndStartIndex);
273
+ this._length = 0;
274
+ this._startIndex = 0;
275
+ this._isChangedLength = false;
276
+ this._isChangedStartIndex = false;
277
+
278
+ // Clear internal caches
279
+ this._values.clear();
280
+ this._isLoaded.clear();
281
+ this._isChanged.clear();
282
+ }
283
+
284
+ /**
285
+ * @method setMultiple
286
+ * @description Sets multiple Address values starting from a specific global index.
287
+ * @param {u32} startIndex - The starting global index.
288
+ * @param {Address[]} values - An array of Address values to set.
289
+ */
290
+ @inline
291
+ public setMultiple(startIndex: u32, values: Address[]): void {
292
+ for (let i: u32 = 0; i < values.length; i++) {
293
+ this.set(<u64>(startIndex + i), values[i]);
294
+ }
295
+ }
296
+
297
+ /**
298
+ * @method getAll
299
+ * @description Retrieves a range of Address values.
300
+ * @param {u32} startIndex - The start index.
301
+ * @param {u32} count - The number of items to get.
302
+ * @returns {Address[]} - The requested Address values.
303
+ */
304
+ @inline
305
+ public getAll(startIndex: u32, count: u32): Address[] {
306
+ assert(startIndex + count <= this._length, 'Requested range exceeds array length');
307
+ const result: Address[] = new Array<Address>(count);
308
+ for (let i: u32 = 0; i < count; i++) {
309
+ result[i] = this.get(<u64>(startIndex + i));
310
+ }
311
+ return result;
312
+ }
313
+
314
+ /**
315
+ * @method toString
316
+ * @description Returns a string representation of the array.
317
+ * @returns {string} - A string of the form "[addr0, addr1, ...]".
318
+ */
319
+ @inline
320
+ public toString(): string {
321
+ let str = '[';
322
+ for (let i: u32 = 0; i < this._length; i++) {
323
+ const value = this.get(<u64>i);
324
+ str += value.toString();
325
+ if (i !== this._length - 1) {
326
+ str += ', ';
327
+ }
328
+ }
329
+ str += ']';
330
+ return str;
331
+ }
332
+
333
+ /**
334
+ * @method toBytes
335
+ * @description Returns the packed Address values as a byte array.
336
+ * @returns {u8[]} - The packed byte array.
337
+ */
338
+ @inline
339
+ public toBytes(): u8[] {
340
+ const bytes: u8[] = new Array<u8>();
341
+ for (let i: u32 = 0; i < this._length; i++) {
342
+ this.ensureValues(i);
343
+ const value = this._values.get(i);
344
+ if (value) {
345
+ const valueBytes = value; // Address is assumed to be or contain a Uint8Array
346
+ for (let j: u32 = 0; j < valueBytes.length; j++) {
347
+ bytes.push(valueBytes[j]);
348
+ }
349
+ }
350
+ }
351
+ return bytes;
352
+ }
353
+
354
+ /**
355
+ * @method reset
356
+ * @description Resets the array by clearing all elements and resetting length and startIndex to zero.
357
+ */
358
+ @inline
359
+ public reset(): void {
360
+ this._length = 0;
361
+ this._startIndex = 0;
362
+ this._isChangedLength = true;
363
+ this._isChangedStartIndex = true;
364
+ this.save();
365
+ }
366
+
367
+ /**
368
+ * @method getLength
369
+ * @description Retrieves the current length of the array.
370
+ * @returns {u64} - The current length.
371
+ */
372
+ @inline
373
+ public getLength(): u64 {
374
+ return this._length;
375
+ }
376
+
377
+ /**
378
+ * @method startingIndex
379
+ * @description Retrieves the current starting index of the array.
380
+ * @returns {u64} - The starting index.
381
+ */
382
+ public startingIndex(): u64 {
383
+ return this._startIndex;
384
+ }
385
+
386
+ /**
387
+ * @method setLength
388
+ * @description Sets the length of the array, truncating if necessary.
389
+ * @param {u64} newLength - The new length.
390
+ */
391
+ public setLength(newLength: u64): void {
392
+ if (newLength > this.MAX_LENGTH) {
393
+ throw new Revert('SetLength operation failed: Length exceeds maximum allowed value.');
394
+ }
395
+
396
+ if (newLength < this._length) {
397
+ // Truncate the array if newLength is smaller
398
+ for (let i: u64 = newLength; i < this._length; i++) {
399
+ this.delete(i);
400
+ }
401
+ }
402
+
403
+ this._length = newLength;
404
+ this._isChangedLength = true;
405
+ }
406
+
407
+ /**
408
+ * @private
409
+ * @method ensureValues
410
+ * @description Loads and caches the Address from the specified storage slot if not already loaded.
411
+ * @param {u32} slotIndex - The index of the storage slot.
412
+ */
413
+ private ensureValues(slotIndex: u32): void {
414
+ if (!this._isLoaded.has(slotIndex)) {
415
+ const storagePointer = this.calculateStoragePointer(slotIndex);
416
+ const storedU256: u256 = Blockchain.getStorageAt(storagePointer, u256.Zero);
417
+ const storedAddress: Address =
418
+ storedU256 == u256.Zero ? this.defaultValue : new Address(storedU256.toBytes());
419
+ this._values.set(slotIndex, storedAddress);
420
+ this._isLoaded.add(slotIndex);
421
+ }
422
+ }
423
+
424
+ /**
425
+ * @private
426
+ * @method calculateStoragePointer
427
+ * @description Calculates the storage pointer for a given slot index.
428
+ * @param {u64} slotIndex - The index of the storage slot.
429
+ * @returns {u256} - The calculated storage pointer.
430
+ */
431
+ private calculateStoragePointer(slotIndex: u64): u256 {
432
+ // Each slot is identified by baseU256Pointer + slotIndex + 1
433
+ // Slot 0: baseU256Pointer + 1
434
+ // Slot 1: baseU256Pointer + 2, etc.
435
+ return SafeMath.add(this.baseU256Pointer, u256.fromU64(slotIndex + 1));
436
+ }
437
+ }
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
 
4
4
  @final
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
4
  import { SafeMath } from '../types/SafeMath';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { SafeMath } from '../types/SafeMath';
4
4
  import { encodePointer } from '../math/abi';
@@ -1,4 +1,4 @@
1
- import { u128, u256 } from 'as-bignum/assembly';
1
+ import { u128, u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
4
  import { SafeMath } from '../types/SafeMath';
@@ -110,9 +110,8 @@ export class StoredU128Array {
110
110
  }
111
111
 
112
112
  const newIndex: u64 = this._length;
113
- const effectiveIndex: u64 = this._startIndex + newIndex;
114
113
  const wrappedIndex: u64 =
115
- effectiveIndex < this.MAX_LENGTH ? effectiveIndex : effectiveIndex % this.MAX_LENGTH;
114
+ newIndex < this.MAX_LENGTH ? newIndex : newIndex % this.MAX_LENGTH;
116
115
  const slotIndex: u32 = <u32>(wrappedIndex / 2);
117
116
  const subIndex: u8 = <u8>(wrappedIndex % 2);
118
117
 
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
4
  import { SafeMath } from '../types/SafeMath';
@@ -106,9 +106,9 @@ export class StoredU16Array {
106
106
  }
107
107
 
108
108
  const newIndex: u64 = this._length;
109
- const effectiveIndex: u64 = this._startIndex + newIndex;
110
109
  const wrappedIndex: u64 =
111
- effectiveIndex < this.MAX_LENGTH ? effectiveIndex : effectiveIndex % this.MAX_LENGTH;
110
+ newIndex < this.MAX_LENGTH ? newIndex : newIndex % this.MAX_LENGTH;
111
+
112
112
  const slotIndex: u64 = wrappedIndex / 16;
113
113
  const subIndex: u8 = <u8>(wrappedIndex % 16);
114
114
 
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { SafeMath } from '../types/SafeMath';
3
3
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
4
4
  import { Blockchain } from '../env';
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { Blockchain } from '../env';
3
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
4
  import { SafeMath } from '../types/SafeMath';
@@ -103,9 +103,8 @@ export class StoredU256Array {
103
103
  }
104
104
 
105
105
  const newIndex: u64 = this._length;
106
- const effectiveIndex: u64 = this._startIndex + newIndex;
107
106
  const wrappedIndex: u64 =
108
- effectiveIndex < this.MAX_LENGTH ? effectiveIndex : effectiveIndex % this.MAX_LENGTH;
107
+ newIndex < this.MAX_LENGTH ? newIndex : newIndex % this.MAX_LENGTH;
109
108
  const slotIndex: u32 = <u32>wrappedIndex;
110
109
 
111
110
  // Ensure the slot is loaded
@@ -2,7 +2,7 @@ import { MemorySlotPointer } from '../memory/MemorySlotPointer';
2
2
  import { Blockchain } from '../env';
3
3
  import { encodePointer } from '../math/abi';
4
4
  import { BytesWriter } from '../buffer/BytesWriter';
5
- import { u256 } from 'as-bignum/assembly';
5
+ import { u256 } from '@btc-vision/as-bignum/assembly';
6
6
 
7
7
  /**
8
8
  * @class StoredU64
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { BytesWriter } from '../buffer/BytesWriter';
3
3
  import { Blockchain } from '../env';
4
4
  import { Box } from '../utils/box';
@@ -1,4 +1,4 @@
1
- import { u128, u256 } from 'as-bignum/assembly';
1
+ import { u128, u256 } from '@btc-vision/as-bignum/assembly';
2
2
 
3
3
  export class SafeMath {
4
4
  public static ZERO: u256 = u256.fromU32(0);
@@ -267,17 +267,7 @@ export class SafeMath {
267
267
  const bitShift = shift % bitsPerSegment;
268
268
 
269
269
  const segments = [value.lo1, value.lo2, value.hi1, value.hi2];
270
-
271
- const result = new Array<u64>(4).fill(0);
272
-
273
- for (let i = 0; i < segments.length; i++) {
274
- if (i + segmentShift < segments.length) {
275
- result[i + segmentShift] |= segments[i] << bitShift;
276
- }
277
- if (bitShift != 0 && i + segmentShift + 1 < segments.length) {
278
- result[i + segmentShift + 1] |= segments[i] >>> (bitsPerSegment - bitShift);
279
- }
280
- }
270
+ const result = SafeMath.shlSegment(segments, segmentShift, bitShift, bitsPerSegment, 4);
281
271
 
282
272
  return new u256(result[0], result[1], result[2], result[3]);
283
273
  }
@@ -302,17 +292,7 @@ export class SafeMath {
302
292
  const bitShift = shift % bitsPerSegment;
303
293
 
304
294
  const segments = [value.lo, value.hi];
305
-
306
- const result = new Array<u64>(2).fill(0);
307
-
308
- for (let i = 0; i < segments.length; i++) {
309
- if (i + segmentShift < segments.length) {
310
- result[i + segmentShift] |= segments[i] << bitShift;
311
- }
312
- if (bitShift != 0 && i + segmentShift + 1 < segments.length) {
313
- result[i + segmentShift + 1] |= segments[i] >>> (bitsPerSegment - bitShift);
314
- }
315
- }
295
+ const result = SafeMath.shlSegment(segments, segmentShift, bitShift, bitsPerSegment, 2);
316
296
 
317
297
  return new u128(result[0], result[1]);
318
298
  }
@@ -329,8 +309,58 @@ export class SafeMath {
329
309
  return u256.xor(a, b);
330
310
  }
331
311
 
332
- public static shr(a: u256, b: u32): u256 {
333
- return u256.shr(a, b);
312
+ public static shr(a: u256, shift: i32): u256 {
313
+ shift &= 255;
314
+ if (shift == 0) return a;
315
+
316
+ const w = shift >>> 6; // how many full 64-bit words to drop
317
+ const b = shift & 63; // how many bits to shift within a word
318
+
319
+ // Extract the words
320
+ let lo1 = a.lo1;
321
+ let lo2 = a.lo2;
322
+ let hi1 = a.hi1;
323
+ let hi2 = a.hi2;
324
+
325
+ // Shift words down by w words
326
+ // For w = 1, move lo2->lo1, hi1->lo2, hi2->hi1, and hi2 = 0
327
+ // For w = 2, move hi1->lo1, hi2->lo2, and zeros in hi1, hi2
328
+ // For w = 3, move hi2->lo1 and zeros in others
329
+ // For w >= 4, everything is zero.
330
+ if (w >= 4) {
331
+ // Shifting by >= 256 bits zeros out everything
332
+ return u256.Zero;
333
+ } else if (w == 3) {
334
+ lo1 = hi2;
335
+ lo2 = 0;
336
+ hi1 = 0;
337
+ hi2 = 0;
338
+ } else if (w == 2) {
339
+ lo1 = hi1;
340
+ lo2 = hi2;
341
+ hi1 = 0;
342
+ hi2 = 0;
343
+ } else if (w == 1) {
344
+ lo1 = lo2;
345
+ lo2 = hi1;
346
+ hi1 = hi2;
347
+ hi2 = 0;
348
+ }
349
+
350
+ // Now apply the bit shift b
351
+ if (b > 0) {
352
+ // Bring down bits from the higher word
353
+ const carryLo2 = hi1 << (64 - b);
354
+ const carryLo1 = lo2 << (64 - b);
355
+ const carryHi1 = hi2 << (64 - b);
356
+
357
+ lo1 = (lo1 >>> b) | carryLo1;
358
+ lo2 = (lo2 >>> b) | carryLo2;
359
+ hi1 = (hi1 >>> b) | carryHi1;
360
+ hi2 = hi2 >>> b;
361
+ }
362
+
363
+ return new u256(lo1, lo2, hi1, hi2);
334
364
  }
335
365
 
336
366
  /**
@@ -360,4 +390,25 @@ export class SafeMath {
360
390
 
361
391
  return n;
362
392
  }
393
+
394
+ private static shlSegment(
395
+ segments: u64[],
396
+ segmentShift: i32,
397
+ bitShift: i32,
398
+ bitsPerSegment: i32,
399
+ fillCount: u8,
400
+ ): u64[] {
401
+ const result = new Array<u64>(fillCount).fill(0);
402
+
403
+ for (let i = 0; i < segments.length; i++) {
404
+ if (i + segmentShift < segments.length) {
405
+ result[i + segmentShift] |= segments[i] << bitShift;
406
+ }
407
+ if (bitShift != 0 && i + segmentShift + 1 < segments.length) {
408
+ result[i + segmentShift + 1] |= segments[i] >>> (bitsPerSegment - bitShift);
409
+ }
410
+ }
411
+
412
+ return result;
413
+ }
363
414
  }
@@ -1,7 +1,7 @@
1
1
  import { Map } from '../generic/Map';
2
2
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
3
3
  import { MemorySlotData } from '../memory/MemorySlot';
4
- import { u256 } from 'as-bignum/assembly';
4
+ import { u256 } from '@btc-vision/as-bignum/assembly';
5
5
  import { BytesReader } from '../buffer/BytesReader';
6
6
 
7
7
  export type PointerStorage = Map<MemorySlotPointer, MemorySlotData<u256>>;
@@ -1,4 +1,4 @@
1
- import { u256 } from 'as-bignum/assembly';
1
+ import { u256 } from '@btc-vision/as-bignum/assembly';
2
2
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
3
3
 
4
4
  import { b32decode as _b32decode, bech32m as _bech32m, fromWords, toWords } from './b32';