@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.
Files changed (59) hide show
  1. package/package.json +44 -53
  2. package/runtime/abort/abort.ts +25 -0
  3. package/runtime/buffer/BytesReader.ts +171 -140
  4. package/runtime/buffer/BytesWriter.ts +120 -152
  5. package/runtime/contracts/DeployableOP_20.ts +29 -15
  6. package/runtime/contracts/OP_NET.ts +4 -1
  7. package/runtime/env/BlockchainEnvironment.ts +79 -137
  8. package/runtime/env/classes/Block.ts +4 -8
  9. package/runtime/env/classes/Transaction.ts +14 -7
  10. package/runtime/env/classes/UTXO.ts +4 -2
  11. package/runtime/env/global.ts +49 -20
  12. package/runtime/events/predefined/MintEvent.ts +1 -1
  13. package/runtime/exports/index.ts +33 -8
  14. package/runtime/generic/AddressMap.ts +7 -5
  15. package/runtime/generic/Map.ts +32 -2
  16. package/runtime/generic/MapU256.ts +7 -5
  17. package/runtime/generic/MapUint8Array.ts +93 -0
  18. package/runtime/index.ts +4 -12
  19. package/runtime/math/abi.ts +71 -11
  20. package/runtime/math/bytes.ts +177 -41
  21. package/runtime/memory/AddressMemoryMap.ts +22 -19
  22. package/runtime/memory/FastUint8Array.ts +122 -0
  23. package/runtime/memory/KeyMerger.ts +25 -23
  24. package/runtime/memory/MultiAddressMemoryMap.ts +11 -8
  25. package/runtime/memory/MultiStringMemoryMap.ts +8 -5
  26. package/runtime/memory/StringMemoryMap.ts +15 -15
  27. package/runtime/memory/Uint8ArrayMerger.ts +22 -15
  28. package/runtime/storage/Serializable.ts +19 -20
  29. package/runtime/storage/StoredAddress.ts +16 -15
  30. package/runtime/storage/StoredBoolean.ts +26 -21
  31. package/runtime/storage/StoredString.ts +158 -102
  32. package/runtime/storage/StoredU256.ts +25 -28
  33. package/runtime/storage/StoredU64.ts +23 -35
  34. package/runtime/storage/arrays/StoredAddressArray.ts +83 -175
  35. package/runtime/storage/arrays/StoredBooleanArray.ts +146 -271
  36. package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
  37. package/runtime/storage/arrays/StoredU128Array.ts +38 -374
  38. package/runtime/storage/arrays/StoredU16Array.ts +34 -420
  39. package/runtime/storage/arrays/StoredU256Array.ts +21 -347
  40. package/runtime/storage/arrays/StoredU32Array.ts +37 -440
  41. package/runtime/storage/arrays/StoredU64Array.ts +66 -0
  42. package/runtime/storage/arrays/StoredU8Array.ts +29 -453
  43. package/runtime/types/Address.ts +72 -5
  44. package/runtime/types/index.ts +1 -4
  45. package/runtime/utils/encodings.ts +5 -6
  46. package/runtime/utils/hex.ts +1 -1
  47. package/runtime/interfaces/DeployContractResponse.ts +0 -12
  48. package/runtime/math/cyrb53.ts +0 -48
  49. package/runtime/math/sha256.ts +0 -12
  50. package/runtime/memory/MemorySlot.ts +0 -1
  51. package/runtime/memory/MemorySlotPointer.ts +0 -3
  52. package/runtime/storage/utils/StorageBacked.ts +0 -5
  53. package/runtime/storage/utils/StorageLayout.ts +0 -7
  54. package/runtime/storage/utils/StorageSlot.ts +0 -106
  55. package/runtime/storage/utils/StorageStruct.ts +0 -23
  56. package/runtime/storage/utils/StorageValue.ts +0 -36
  57. package/runtime/tests/assert.ts +0 -11
  58. package/runtime/tests/env.ts +0 -7
  59. package/runtime/tests/tests.ts +0 -28
@@ -0,0 +1,122 @@
1
+ import { Revert } from '../types/Revert';
2
+ import { ArrayBuffer } from 'arraybuffer';
3
+
4
+ export class FastUint8Array {
5
+ public length: i32;
6
+ private ptr: usize;
7
+
8
+ [key: number]: u8;
9
+
10
+ constructor(length: i32) {
11
+ if (length < 0) {
12
+ throw new Revert('Negative length in FastUint8Array constructor');
13
+ }
14
+
15
+ this.length = length;
16
+ this.ptr = __alloc(<usize>length);
17
+ }
18
+
19
+ public static fromUint8Array(arr: Uint8Array): FastUint8Array {
20
+ const buffer = new FastUint8Array(arr.length);
21
+ for (let i: u32 = 0; i < arr.length; i++) {
22
+ buffer[i] = arr[i];
23
+ }
24
+
25
+ return buffer;
26
+ }
27
+
28
+ toArrayBuffer(): ArrayBuffer {
29
+ const arr = new Uint8Array(this.length);
30
+ for (let i: u32 = 0; i < arr.length; i++) {
31
+ arr[i] = this[i];
32
+ }
33
+
34
+ return arr.buffer;
35
+ }
36
+
37
+ /**
38
+ * Fills the buffer with a specified byte value.
39
+ */
40
+ fill(value: u8): void {
41
+ memory.fill(this.ptr, value, <usize>this.length);
42
+ }
43
+
44
+ /**
45
+ * Copies bytes from another FastUint8Array into this one, starting at `destOffset`.
46
+ */
47
+ copyFrom(source: FastUint8Array, destOffset: i32 = 0): void {
48
+ if (destOffset < 0) {
49
+ throw new Revert(`Negative destOffset in copyFrom: ${destOffset}`);
50
+ }
51
+
52
+ let maxBytes = source.length;
53
+ const destRemaining = this.length - destOffset;
54
+ if (destRemaining < maxBytes) {
55
+ maxBytes = destRemaining;
56
+ }
57
+
58
+ if (maxBytes <= 0) return;
59
+
60
+ memory.copy(
61
+ this.ptr + <usize>destOffset,
62
+ source.ptr,
63
+ <usize>maxBytes,
64
+ );
65
+ }
66
+
67
+ free(): void {
68
+ if (this.ptr != 0) {
69
+ __free(this.ptr);
70
+ this.ptr = 0;
71
+ this.length = 0;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Safe read operator: buffer[i]
77
+ * Throws on out-of-bounds.
78
+ */
79
+ @operator('[]')
80
+ private __get(index: i32): u8 {
81
+ if (<u32>index >= <u32>this.length) {
82
+ throw new Revert('Index out of range in __get');
83
+ }
84
+ return load<u8>(this.ptr + <usize>index);
85
+ }
86
+
87
+ /**
88
+ * Safe write operator: buffer[i] = value
89
+ * Throws on out-of-bounds.
90
+ */
91
+ @operator('[]=')
92
+ private __set(index: i32, value: u8): void {
93
+ if (<u32>index >= <u32>this.length) {
94
+ throw new Revert('Index out of range in __set');
95
+ }
96
+ store<u8>(this.ptr + <usize>index, value);
97
+ }
98
+
99
+ /**
100
+ * Braces read operator: buffer{i}
101
+ * Now also throws on out-of-bounds for safety.
102
+ */
103
+ @operator('{}')
104
+ private __uget(index: i32): u8 {
105
+ if (<u32>index >= <u32>this.length) {
106
+ throw new Revert('Index out of range in __uget');
107
+ }
108
+ return load<u8>(this.ptr + <usize>index);
109
+ }
110
+
111
+ /**
112
+ * Braces write operator: buffer{i} = value
113
+ * Now also throws on out-of-bounds.
114
+ */
115
+ @operator('{}=')
116
+ private __uset(index: i32, value: u8): void {
117
+ if (<u32>index >= <u32>this.length) {
118
+ throw new Revert('Index out of range in __uset');
119
+ }
120
+ store<u8>(this.ptr + <usize>index, value);
121
+ }
122
+ }
@@ -1,44 +1,34 @@
1
- import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from '@btc-vision/as-bignum/assembly';
3
- import { Blockchain } from '../env';
4
- import { MemorySlotPointer } from './MemorySlotPointer';
5
- import { encodePointer } from '../math/abi';
6
1
  import { BytesWriter } from '../buffer/BytesWriter';
2
+ import { Blockchain } from '../env';
3
+ import { encodePointerUnknownLength } from '../math/abi';
4
+
7
5
 
8
6
  @final
9
- export class KeyMerger<K extends string, K2 extends string, V extends MemorySlotData<u256>> {
7
+ export class KeyMerger<K extends string, K2 extends string, V extends Uint8Array> {
10
8
  public parentKey: K;
11
-
12
9
  public pointer: u16;
13
10
 
14
- constructor(
15
- parent: K,
16
- pointer: u16,
17
- private readonly defaultValue: V,
18
- ) {
11
+ constructor(parent: K, pointer: u16) {
19
12
  this.pointer = pointer;
20
-
21
13
  this.parentKey = parent;
22
14
  }
23
15
 
24
16
  public set(key2: K2, value: V): this {
25
- const mergedKey: string = `${this.parentKey}${key2}`;
26
- const keyHash: MemorySlotPointer = this.encodePointer(mergedKey);
17
+ const mergedKey: string = this.mergeKey(key2);
18
+ const keyHash: Uint8Array = this.encodePointer(mergedKey);
27
19
 
28
20
  Blockchain.setStorageAt(keyHash, value);
29
21
 
30
22
  return this;
31
23
  }
32
24
 
33
- public get(key: K): MemorySlotData<u256> {
34
- const mergedKey: string = `${this.parentKey}${key}`;
35
-
36
- return Blockchain.getStorageAt(this.encodePointer(mergedKey), this.defaultValue);
25
+ public get(key: K): Uint8Array {
26
+ const mergedKey: string = this.mergeKey(key);
27
+ return Blockchain.getStorageAt(this.encodePointer(mergedKey));
37
28
  }
38
29
 
39
30
  public has(key: K): bool {
40
- const mergedKey: string = `${this.parentKey}${key}`;
41
-
31
+ const mergedKey: string = this.mergeKey(key);
42
32
  return Blockchain.hasStorageAt(this.encodePointer(mergedKey));
43
33
  }
44
34
 
@@ -52,10 +42,22 @@ export class KeyMerger<K extends string, K2 extends string, V extends MemorySlot
52
42
  throw new Error('Clear method not implemented.');
53
43
  }
54
44
 
55
- private encodePointer(key: string): MemorySlotPointer {
45
+ /**
46
+ * Merges the parentKey and the provided key by prefixing each with its length.
47
+ * This avoids collisions such as:
48
+ * parentKey = "abc", key = "def" => "3:abc3:def"
49
+ * parentKey = "ab", key = "cdef" => "2:ab4:cdef"
50
+ */
51
+ @inline
52
+ private mergeKey(key: string): string {
53
+ return `${this.parentKey.length}:${this.parentKey}${key.length}:${key}`;
54
+ }
55
+
56
+ @inline
57
+ private encodePointer(key: string): Uint8Array {
56
58
  const writer = new BytesWriter(key.length);
57
59
  writer.writeString(key);
58
60
 
59
- return encodePointer(this.pointer, writer.getBuffer());
61
+ return encodePointerUnknownLength(this.pointer, writer.getBuffer());
60
62
  }
61
63
  }
@@ -1,51 +1,54 @@
1
- import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from '@btc-vision/as-bignum/assembly';
3
1
  import { Uint8ArrayMerger } from './Uint8ArrayMerger';
4
2
  import { Address } from '../types/Address';
5
3
 
6
4
  @final
7
- export class MultiAddressMemoryMap<V extends MemorySlotData<u256>> extends Map<
5
+ export class MultiAddressMemoryMap extends Map<
8
6
  Address,
9
- Uint8ArrayMerger<V>
7
+ Uint8ArrayMerger
10
8
  > {
11
9
  public pointer: u16;
12
10
 
13
11
  constructor(
14
12
  pointer: u16,
15
- private readonly defaultValue: V,
16
13
  ) {
17
14
  super();
18
15
 
19
16
  this.pointer = pointer;
20
17
  }
21
18
 
22
- public get(key: Address): Uint8ArrayMerger<V> {
19
+ @inline
20
+ public get(key: Address): Uint8ArrayMerger {
23
21
  this.createKeyMerger(key);
24
22
 
25
23
  return super.get(key);
26
24
  }
27
25
 
28
- public set(key: Address, value: Uint8ArrayMerger<V>): this {
26
+ @inline
27
+ public set(key: Address, value: Uint8ArrayMerger): this {
29
28
  this.createKeyMerger(key);
30
29
 
31
30
  return <this>super.set(key, value);
32
31
  }
33
32
 
33
+ @inline
34
34
  public has(key: Address): bool {
35
35
  return super.has(key);
36
36
  }
37
37
 
38
+ @inline
38
39
  public delete(key: Address): bool {
39
40
  return super.delete(key);
40
41
  }
41
42
 
43
+ @inline
42
44
  public clear(): void {
43
45
  super.clear();
44
46
  }
45
47
 
48
+ @inline
46
49
  private createKeyMerger(key: Address): void {
47
50
  if (!super.has(key)) {
48
- super.set(key, new Uint8ArrayMerger<V>(key, this.pointer, this.defaultValue));
51
+ super.set(key, new Uint8ArrayMerger(key, this.pointer));
49
52
  }
50
53
  }
51
54
  }
@@ -1,30 +1,29 @@
1
- import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from '@btc-vision/as-bignum/assembly';
3
1
  import { KeyMerger } from './KeyMerger';
4
2
 
5
3
  @final
6
4
  export class MultiStringMemoryMap<
7
5
  K extends string,
8
6
  K2 extends string,
9
- V extends MemorySlotData<u256>,
7
+ V extends Uint8Array,
10
8
  > extends Map<K, KeyMerger<K, K2, V>> {
11
9
  public pointer: u16;
12
10
 
13
11
  constructor(
14
12
  pointer: u16,
15
- private readonly defaultValue: V,
16
13
  ) {
17
14
  super();
18
15
 
19
16
  this.pointer = pointer;
20
17
  }
21
18
 
19
+ @inline
22
20
  public get(key: K): KeyMerger<K, K2, V> {
23
21
  this.createKeyMerger(key);
24
22
 
25
23
  return super.get(key);
26
24
  }
27
25
 
26
+ @inline
28
27
  public setUpperKey(key: K, key2: K2, value: V): this {
29
28
  this.createKeyMerger(key);
30
29
 
@@ -36,27 +35,31 @@ export class MultiStringMemoryMap<
36
35
  return this;
37
36
  }
38
37
 
38
+ @inline
39
39
  public set(key: K, value: KeyMerger<K, K2, V>): this {
40
40
  this.createKeyMerger(key);
41
41
 
42
42
  return <this>super.set(key, value);
43
43
  }
44
44
 
45
+ @inline
45
46
  public has(key: K): bool {
46
47
  return super.has(key);
47
48
  }
48
49
 
50
+ @inline
49
51
  public delete(key: K): bool {
50
52
  return super.delete(key);
51
53
  }
52
54
 
55
+ @inline
53
56
  public clear(): void {
54
57
  super.clear();
55
58
  }
56
59
 
57
60
  private createKeyMerger(key: K): void {
58
61
  if (!super.has(key)) {
59
- super.set(key, new KeyMerger<K, K2, V>(key, this.pointer, this.defaultValue));
62
+ super.set(key, new KeyMerger<K, K2, V>(key, this.pointer));
60
63
  }
61
64
  }
62
65
  }
@@ -1,43 +1,43 @@
1
- import { MemorySlotPointer } from './MemorySlotPointer';
2
1
  import { Blockchain } from '../env';
3
- import { encodePointer } from '../math/abi';
4
- import { MemorySlotData } from './MemorySlot';
5
- import { u256 } from '@btc-vision/as-bignum/assembly';
2
+ import { encodePointerUnknownLength } from '../math/abi';
6
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
+ import { EMPTY_BUFFER } from '../math/bytes';
7
5
 
8
6
  @final
9
- export class StringMemoryMap<K extends string, V extends MemorySlotData<u256>> {
7
+ export class StringMemoryMap<K extends string> {
10
8
  public pointer: u16;
11
9
 
12
10
  constructor(
13
11
  pointer: u16,
14
- private readonly defaultValue: V,
15
12
  ) {
16
13
  this.pointer = pointer;
17
14
  }
18
15
 
19
- public set(key: K, value: V): this {
20
- const keyHash: MemorySlotPointer = this.encodePointer(key);
16
+ @inline
17
+ public set(key: K, value: Uint8Array): this {
18
+ const keyHash: Uint8Array = this.encodePointer(key);
21
19
  Blockchain.setStorageAt(keyHash, value);
22
20
 
23
21
  return this;
24
22
  }
25
23
 
26
- public get(key: K): MemorySlotData<u256> {
27
- const keyHash: MemorySlotPointer = this.encodePointer(key);
24
+ @inline
25
+ public get(key: K): Uint8Array {
26
+ const keyHash: Uint8Array = this.encodePointer(key);
28
27
 
29
- return Blockchain.getStorageAt(keyHash, this.defaultValue);
28
+ return Blockchain.getStorageAt(keyHash);
30
29
  }
31
30
 
31
+ @inline
32
32
  public has(key: K): bool {
33
- const keyHash: MemorySlotPointer = this.encodePointer(key);
33
+ const keyHash: Uint8Array = this.encodePointer(key);
34
34
 
35
35
  return Blockchain.hasStorageAt(keyHash);
36
36
  }
37
37
 
38
38
  @unsafe
39
39
  public delete(key: K): bool {
40
- this.set(key, this.defaultValue);
40
+ this.set(key, EMPTY_BUFFER);
41
41
 
42
42
  return true;
43
43
  }
@@ -47,10 +47,10 @@ export class StringMemoryMap<K extends string, V extends MemorySlotData<u256>> {
47
47
  throw new Error('Method not implemented.');
48
48
  }
49
49
 
50
- private encodePointer(key: K): MemorySlotPointer {
50
+ private encodePointer(key: K): Uint8Array {
51
51
  const writer = new BytesWriter(key.length);
52
52
  writer.writeString(key);
53
53
 
54
- return encodePointer(this.pointer, writer.getBuffer());
54
+ return encodePointerUnknownLength(this.pointer, writer.getBuffer());
55
55
  }
56
56
  }
@@ -1,12 +1,10 @@
1
- import { MemorySlotData } from './MemorySlot';
2
- import { u256 } from '@btc-vision/as-bignum/assembly';
3
1
  import { Blockchain } from '../env';
4
- import { MemorySlotPointer } from './MemorySlotPointer';
5
- import { encodePointer } from '../math/abi';
2
+ import { encodePointerUnknownLength } from '../math/abi';
6
3
  import { BytesWriter } from '../buffer/BytesWriter';
4
+ import { u256 } from '@btc-vision/as-bignum/assembly';
7
5
 
8
6
  @final
9
- export class Uint8ArrayMerger<V extends MemorySlotData<u256>> {
7
+ export class Uint8ArrayMerger {
10
8
  public parentKey: Uint8Array;
11
9
 
12
10
  public pointer: u16;
@@ -14,28 +12,37 @@ export class Uint8ArrayMerger<V extends MemorySlotData<u256>> {
14
12
  constructor(
15
13
  parent: Uint8Array,
16
14
  pointer: u16,
17
- private readonly defaultValue: V,
18
15
  ) {
19
16
  this.pointer = pointer;
20
17
 
21
18
  this.parentKey = parent;
22
19
  }
23
20
 
24
- public set(key: Uint8Array, value: V): this {
25
- const keyHash: MemorySlotPointer = this.getKeyHash(key);
21
+ public setAsUint8Array(key: Uint8Array, value: Uint8Array): this {
22
+ const keyHash: Uint8Array = this.getKeyHash(key);
26
23
  Blockchain.setStorageAt(keyHash, value);
27
24
 
28
25
  return this;
29
26
  }
30
27
 
31
- public get(key: Uint8Array): MemorySlotData<u256> {
32
- const keyHash: MemorySlotPointer = this.getKeyHash(key);
28
+ public set(key: Uint8Array, value: u256): this {
29
+ return this.setAsUint8Array(key, value.toUint8Array(true));
30
+ }
31
+
32
+ public getAsUint8Array(key: Uint8Array): Uint8Array {
33
+ const keyHash: Uint8Array = this.getKeyHash(key);
34
+
35
+ return Blockchain.getStorageAt(keyHash);
36
+ }
37
+
38
+ public get(key: Uint8Array): u256 {
39
+ const data = this.getAsUint8Array(key);
33
40
 
34
- return Blockchain.getStorageAt(keyHash, this.defaultValue);
41
+ return u256.fromUint8ArrayBE(data);
35
42
  }
36
43
 
37
44
  public has(key: Uint8Array): bool {
38
- const mergedKey: MemorySlotPointer = this.getKeyHash(key);
45
+ const mergedKey: Uint8Array = this.getKeyHash(key);
39
46
 
40
47
  return Blockchain.hasStorageAt(mergedKey);
41
48
  }
@@ -50,7 +57,7 @@ export class Uint8ArrayMerger<V extends MemorySlotData<u256>> {
50
57
  throw new Error('Clear method not implemented.');
51
58
  }
52
59
 
53
- private getKeyHash(key: Uint8Array): MemorySlotPointer {
60
+ private getKeyHash(key: Uint8Array): Uint8Array {
54
61
  const writer: BytesWriter = new BytesWriter(key.byteLength + this.parentKey.byteLength);
55
62
 
56
63
  writer.writeBytes(this.parentKey);
@@ -59,7 +66,7 @@ export class Uint8ArrayMerger<V extends MemorySlotData<u256>> {
59
66
  return this.encodePointer(writer);
60
67
  }
61
68
 
62
- private encodePointer(writer: BytesWriter): MemorySlotPointer {
63
- return encodePointer(this.pointer, writer.getBuffer());
69
+ private encodePointer(writer: BytesWriter): Uint8Array {
70
+ return encodePointerUnknownLength(this.pointer, writer.getBuffer());
64
71
  }
65
72
  }
@@ -1,18 +1,19 @@
1
- import { u256 } from '@btc-vision/as-bignum/assembly';
2
1
  import { BytesReader } from '../buffer/BytesReader';
3
2
  import { BytesWriter } from '../buffer/BytesWriter';
4
3
  import { Blockchain } from '../env';
5
4
  import { encodePointer } from '../math/abi';
6
- import { MemorySlotPointer } from '../memory/MemorySlotPointer';
7
5
  import { Revert } from '../types/Revert';
8
- import { U256_BYTE_LENGTH } from '../utils';
6
+
7
+ export const SERIALIZED_POINTER_LENGTH: u8 = 29;
9
8
 
10
9
  // Similar to a struct in Solidity. (Use in worst case scenario, consume a lot of gas)
11
10
  export abstract class Serializable {
12
11
  protected pointer: u16;
13
- protected subPointer: MemorySlotPointer;
12
+ protected subPointer: Uint8Array;
13
+
14
+ protected constructor(pointer: u16, subPointer: Uint8Array) {
15
+ if (subPointer.length !== SERIALIZED_POINTER_LENGTH) throw new Revert(`Sub pointer length must be ${SERIALIZED_POINTER_LENGTH} bytes.`);
14
16
 
15
- protected constructor(pointer: u16, subPointer: MemorySlotPointer) {
16
17
  this.pointer = pointer;
17
18
  this.subPointer = subPointer;
18
19
  }
@@ -24,14 +25,14 @@ export abstract class Serializable {
24
25
 
25
26
  public abstract readFromBuffer(reader: BytesReader): void;
26
27
 
27
- public abstract exists(chunk: u256, index: u8): boolean;
28
+ public abstract exists(chunk: Uint8Array, index: u8): boolean;
28
29
 
29
30
  public load(): boolean {
30
- const chunks: u256[] = [];
31
+ const chunks: Uint8Array[] = [];
31
32
 
32
33
  for (let index: u8 = 0; index < this.chunkCount; index++) {
33
34
  const pointer = this.getPointer(this.subPointer, index);
34
- const chunk: u256 = Blockchain.getStorageAt(pointer, u256.Zero);
35
+ const chunk: Uint8Array = Blockchain.getStorageAt(pointer);
35
36
 
36
37
  if (!this.exists(chunk, index)) {
37
38
  return false;
@@ -49,7 +50,7 @@ export abstract class Serializable {
49
50
  public save(): void {
50
51
  const writer: BytesWriter = this.writeToBuffer();
51
52
  const buffer = writer.getBuffer();
52
- const chunks: u256[] = this.bytesToChunks(buffer);
53
+ const chunks: Uint8Array[] = this.bytesToChunks(buffer);
53
54
 
54
55
  if (chunks.length !== this.chunkCount) {
55
56
  throw new Revert(
@@ -69,8 +70,8 @@ export abstract class Serializable {
69
70
  }
70
71
  }
71
72
 
72
- protected bytesToChunks(buffer: Uint8Array): u256[] {
73
- const chunks: u256[] = [];
73
+ protected bytesToChunks(buffer: Uint8Array): Uint8Array[] {
74
+ const chunks: Uint8Array[] = [];
74
75
 
75
76
  for (let index: i32 = 0; index < buffer.byteLength; index += 32) {
76
77
  if (chunks.length === 256) {
@@ -78,13 +79,13 @@ export abstract class Serializable {
78
79
  }
79
80
 
80
81
  const chunk = buffer.slice(index, index + 32);
81
- chunks.push(u256.fromBytes(chunk, true));
82
+ chunks.push(chunk);
82
83
  }
83
84
 
84
85
  return chunks;
85
86
  }
86
87
 
87
- protected chunksToBytes(chunks: u256[]): BytesReader {
88
+ protected chunksToBytes(chunks: Uint8Array[]): BytesReader {
88
89
  if (this.chunkCount > u8(255)) {
89
90
  throw new Revert(`Too many chunks received. You may only write up to 8160 bytes per object.`);
90
91
  }
@@ -93,7 +94,7 @@ export abstract class Serializable {
93
94
  let offset: i32 = 0;
94
95
 
95
96
  for (let indexChunk: i32 = 0; indexChunk < chunks.length; indexChunk++) {
96
- const bytes: u8[] = chunks[indexChunk].toBytes(true);
97
+ const bytes: Uint8Array = chunks[indexChunk];
97
98
  for (let indexByte: i32 = 0; indexByte < bytes.length; indexByte++) {
98
99
  buffer[offset++] = bytes[indexByte];
99
100
  }
@@ -102,12 +103,10 @@ export abstract class Serializable {
102
103
  return new BytesReader(buffer);
103
104
  }
104
105
 
105
- protected getPointer(subPointer: u256, index: u8): u256 {
106
- const writer = new BytesWriter(U256_BYTE_LENGTH);
107
- writer.writeU256(subPointer);
108
-
109
- // Discard the first byte for offset.
110
- writer.writeU8At(index, 0);
106
+ protected getPointer(subPointer: Uint8Array, index: u8): Uint8Array {
107
+ const writer = new BytesWriter(30);
108
+ writer.writeU8(index);
109
+ writer.writeBytes(subPointer);
111
110
 
112
111
  return encodePointer(this.pointer, writer.getBuffer());
113
112
  }
@@ -1,31 +1,28 @@
1
- import { u256 } from '@btc-vision/as-bignum/assembly';
2
- import { BytesWriter } from '../buffer/BytesWriter';
3
1
  import { Blockchain } from '../env';
4
2
  import { encodePointer } from '../math/abi';
5
3
  import { Address } from '../types/Address';
4
+ import { EMPTY_POINTER } from '../math/bytes';
5
+ import { eqUint } from '../generic/MapUint8Array';
6
6
 
7
+ /**
8
+ * Default is Address.dead();
9
+ */
7
10
  @final
8
11
  export class StoredAddress {
9
- private readonly addressPointer: u256;
10
- private readonly defaultValue: u256;
12
+ private readonly addressPointer: Uint8Array;
11
13
 
12
- constructor(public pointer: u16, defaultValue: Address) {
13
- const writer = new BytesWriter(32);
14
-
15
- this.defaultValue = u256.fromBytes(defaultValue);
16
- this.addressPointer = encodePointer(pointer, writer.getBuffer());
14
+ constructor(public pointer: u16) {
15
+ this.addressPointer = encodePointer(pointer, EMPTY_POINTER);
17
16
  }
18
17
 
19
- private _value: Address = new Address();
18
+ private _value: Address = Address.dead();
20
19
 
21
- @inline
22
20
  public get value(): Address {
23
21
  this.ensureValue();
24
22
 
25
23
  return this._value;
26
24
  }
27
25
 
28
- @inline
29
26
  public set value(value: Address) {
30
27
  if (value === this.value) {
31
28
  return;
@@ -33,11 +30,15 @@ export class StoredAddress {
33
30
 
34
31
  this._value = value;
35
32
 
36
- Blockchain.setStorageAt(this.addressPointer, u256.fromBytes(this._value));
33
+ Blockchain.setStorageAt(this.addressPointer, this._value);
34
+ }
35
+
36
+ public isDead(): bool {
37
+ return eqUint(Address.dead(), this.value);
37
38
  }
38
39
 
39
40
  private ensureValue(): void {
40
- const value = Blockchain.getStorageAt(this.addressPointer, this.defaultValue);
41
- this._value.set(value.toBytes());
41
+ const value = Blockchain.getStorageAt(this.addressPointer);
42
+ this._value.set(value);
42
43
  }
43
44
  }