@btc-vision/btc-runtime 1.1.6 → 1.1.8

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.
@@ -1,5 +1,5 @@
1
1
  import { IBTC } from '../interfaces/IBTC';
2
- import { Address } from '../types/Address';
2
+ import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
3
3
  import { Blockchain } from '../env';
4
4
  import { Calldata } from '../universal/ABIRegistry';
5
5
  import { BytesWriter } from '../buffer/BytesWriter';
@@ -14,8 +14,6 @@ export class OP_NET implements IBTC {
14
14
  false,
15
15
  );
16
16
 
17
- constructor() {}
18
-
19
17
  public get address(): string {
20
18
  return Blockchain.contractAddress;
21
19
  }
@@ -42,13 +40,15 @@ export class OP_NET implements IBTC {
42
40
  }
43
41
 
44
42
  public callView(method: Selector): BytesWriter {
45
- const response = new BytesWriter();
43
+ let response: BytesWriter;
46
44
 
47
45
  switch (method) {
48
46
  case encodeSelector('address'):
47
+ response = new BytesWriter(ADDRESS_BYTE_LENGTH);
49
48
  response.writeAddress(this.address);
50
49
  break;
51
50
  case encodeSelector('owner'):
51
+ response = new BytesWriter(ADDRESS_BYTE_LENGTH);
52
52
  response.writeAddress(this.owner);
53
53
  break;
54
54
  default:
@@ -1,4 +1,4 @@
1
- import { Address, PotentialAddress } from '../types/Address';
1
+ import { Address, ADDRESS_BYTE_LENGTH, PotentialAddress } from '../types/Address';
2
2
  import { MemorySlotPointer } from '../memory/MemorySlotPointer';
3
3
  import { MemorySlotData } from '../memory/MemorySlot';
4
4
  import { u256 } from 'as-bignum/assembly';
@@ -35,8 +35,6 @@ export class BlockchainEnvironment {
35
35
 
36
36
  private _selfContract: Potential<OP_NET> = null;
37
37
 
38
- constructor() {}
39
-
40
38
  private _txOrigin: PotentialAddress = null;
41
39
 
42
40
  public get txOrigin(): Address {
@@ -66,13 +64,7 @@ export class BlockchainEnvironment {
66
64
  private _contract: Potential<() => OP_NET> = null;
67
65
 
68
66
  public get contract(): OP_NET {
69
- if (!this._contract) {
70
- throw this.error('Contract is required');
71
- }
72
-
73
- if (!this._selfContract) {
74
- this._selfContract = this._contract();
75
- }
67
+ this.createContractIfNotExists();
76
68
 
77
69
  return this._selfContract as OP_NET;
78
70
  }
@@ -133,7 +125,7 @@ export class BlockchainEnvironment {
133
125
 
134
126
  this._timestamp = reader.readU64();
135
127
 
136
- this.contract;
128
+ this.createContractIfNotExists();
137
129
  }
138
130
 
139
131
  public call(destinationContract: Address, calldata: BytesWriter): BytesReader {
@@ -145,7 +137,7 @@ export class BlockchainEnvironment {
145
137
  throw this.error('Destination contract is required');
146
138
  }
147
139
 
148
- const call = new BytesWriter();
140
+ const call = new BytesWriter(ADDRESS_BYTE_LENGTH + calldata.bufferLength() + 4);
149
141
  call.writeAddress(destinationContract);
150
142
  call.writeBytesWithLength(calldata.getBuffer());
151
143
 
@@ -155,7 +147,7 @@ export class BlockchainEnvironment {
155
147
  }
156
148
 
157
149
  public log(data: string): void {
158
- const writer = new BytesWriter();
150
+ const writer = new BytesWriter(data.length + 2);
159
151
  writer.writeStringWithLength(data);
160
152
 
161
153
  const buffer = writer.getBuffer();
@@ -183,7 +175,7 @@ export class BlockchainEnvironment {
183
175
  const event: NetEvent = this.events[i];
184
176
 
185
177
  buffer.writeStringWithLength(event.eventType);
186
- buffer.writeU64(event.getEventDataSelector());
178
+ buffer.writeU64(0); //event.getEventDataSelector()
187
179
  buffer.writeBytesWithLength(event.getEventData());
188
180
  }
189
181
 
@@ -191,7 +183,7 @@ export class BlockchainEnvironment {
191
183
  }
192
184
 
193
185
  public encodeVirtualAddress(virtualAddress: Uint8Array): Address {
194
- const writer: BytesWriter = new BytesWriter();
186
+ const writer: BytesWriter = new BytesWriter(virtualAddress.byteLength + 4);
195
187
  writer.writeBytesWithLength(virtualAddress);
196
188
 
197
189
  const buffer: Uint8Array = writer.getBuffer();
@@ -221,7 +213,7 @@ export class BlockchainEnvironment {
221
213
  existingAddress: Address,
222
214
  salt: u256,
223
215
  ): DeployContractResponse {
224
- const writer = new BytesWriter();
216
+ const writer = new BytesWriter(ADDRESS_BYTE_LENGTH + 32);
225
217
  writer.writeAddress(existingAddress);
226
218
  writer.writeU256(salt);
227
219
 
@@ -280,6 +272,16 @@ export class BlockchainEnvironment {
280
272
  return ABIRegistry.getWriteMethods();
281
273
  }
282
274
 
275
+ private createContractIfNotExists(): void {
276
+ if (!this._contract) {
277
+ throw this.error('Contract is required');
278
+ }
279
+
280
+ if (!this._selfContract) {
281
+ this._selfContract = this._contract();
282
+ }
283
+ }
284
+
283
285
  private error(msg: string): Error {
284
286
  return new Error(`${BlockchainEnvironment.runtimeException}: ${msg}`);
285
287
  }
@@ -287,7 +289,7 @@ export class BlockchainEnvironment {
287
289
  private _internalSetStorageAt(pointerHash: u256, value: MemorySlotData<u256>): void {
288
290
  this.storage.set(pointerHash, value);
289
291
 
290
- const writer: BytesWriter = new BytesWriter();
292
+ const writer: BytesWriter = new BytesWriter(64);
291
293
  writer.writeU256(pointerHash);
292
294
  writer.writeU256(value);
293
295
 
@@ -301,7 +303,7 @@ export class BlockchainEnvironment {
301
303
  }
302
304
 
303
305
  // we attempt to load the requested pointer.
304
- const writer = new BytesWriter();
306
+ const writer = new BytesWriter(32);
305
307
  writer.writeU256(pointer);
306
308
 
307
309
  const result: Uint8Array = loadPointer(writer.getBuffer());
@@ -1,32 +1,32 @@
1
- // @ts-ignore
2
- @external('env', 'load')
3
- export declare function loadPointer(data: Uint8Array): Uint8Array;
4
-
5
- // @ts-ignore
6
- @external('env', 'store')
7
- export declare function storePointer(data: Uint8Array): Uint8Array;
8
-
9
- // @ts-ignore
10
- @external('env', 'deploy')
11
- export declare function deploy(data: Uint8Array): Uint8Array;
12
-
13
- // @ts-ignore
14
- @external('env', 'deployFromAddress')
15
- export declare function deployFromAddress(data: Uint8Array): Uint8Array;
16
-
17
- // @ts-ignore
18
- @external('env', 'call')
19
- export declare function callContract(data: Uint8Array): Uint8Array;
20
-
21
- // @ts-ignore
22
- @external('env', 'log')
23
- export declare function log(data: Uint8Array): void;
24
-
25
- // @ts-ignore
26
- @external('env', 'encodeAddress')
27
- export declare function encodeAddress(data: Uint8Array): Uint8Array;
28
-
29
-
30
- // @ts-ignore
31
- @external('env', 'sha256')
32
- export declare function sha256(data: Uint8Array): Uint8Array;
1
+ // @ts-ignore
2
+ @external('env', 'load')
3
+ export declare function loadPointer(data: Uint8Array): Uint8Array;
4
+
5
+ // @ts-ignore
6
+ @external('env', 'store')
7
+ export declare function storePointer(data: Uint8Array): Uint8Array;
8
+
9
+ // @ts-ignore
10
+ @external('env', 'deploy')
11
+ export declare function deploy(data: Uint8Array): Uint8Array;
12
+
13
+ // @ts-ignore
14
+ @external('env', 'deployFromAddress')
15
+ export declare function deployFromAddress(data: Uint8Array): Uint8Array;
16
+
17
+ // @ts-ignore
18
+ @external('env', 'call')
19
+ export declare function callContract(data: Uint8Array): Uint8Array;
20
+
21
+ // @ts-ignore
22
+ @external('env', 'log')
23
+ export declare function log(data: Uint8Array): void;
24
+
25
+ // @ts-ignore
26
+ @external('env', 'encodeAddress')
27
+ export declare function encodeAddress(data: Uint8Array): Uint8Array;
28
+
29
+
30
+ // @ts-ignore
31
+ @external('env', 'sha256')
32
+ export declare function sha256(data: Uint8Array): Uint8Array;
@@ -13,10 +13,6 @@ export abstract class NetEvent {
13
13
  return this.data.bufferLength();
14
14
  }
15
15
 
16
- public getEventDataSelector(): u64 {
17
- return this.data.getSelectorDataType();
18
- }
19
-
20
16
  public getEventData(): Uint8Array {
21
17
  if (this.data.bufferLength() > MAX_EVENT_DATA_SIZE) {
22
18
  throw new Error('Event data length exceeds maximum length.');
@@ -1,12 +1,12 @@
1
1
  import { u256 } from 'as-bignum/assembly';
2
- import { Address } from '../../types/Address';
2
+ import { Address, ADDRESS_BYTE_LENGTH } from '../../types/Address';
3
3
  import { NetEvent } from '../NetEvent';
4
4
  import { BytesWriter } from '../../buffer/BytesWriter';
5
5
 
6
6
  @final
7
7
  export class ApproveEvent extends NetEvent {
8
8
  constructor(owner: Address, spender: Address, value: u256) {
9
- const data: BytesWriter = new BytesWriter(1, true);
9
+ const data: BytesWriter = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + 32);
10
10
  data.writeAddress(owner);
11
11
  data.writeAddress(spender);
12
12
  data.writeU256(value);
@@ -5,7 +5,7 @@ import { BytesWriter } from '../../buffer/BytesWriter';
5
5
  @final
6
6
  export class BurnEvent extends NetEvent {
7
7
  constructor(amount: u256) {
8
- const data: BytesWriter = new BytesWriter(1, true);
8
+ const data: BytesWriter = new BytesWriter(32);
9
9
  data.writeU256(amount);
10
10
 
11
11
  super('Burn', data);
@@ -5,7 +5,7 @@ import { BytesWriter } from '../../buffer/BytesWriter';
5
5
  @final
6
6
  export class ClaimEvent extends NetEvent {
7
7
  constructor(amount: u256) {
8
- const data: BytesWriter = new BytesWriter(1, true);
8
+ const data: BytesWriter = new BytesWriter(32);
9
9
  data.writeU256(amount);
10
10
 
11
11
  super('Claim', data);
@@ -1,12 +1,12 @@
1
1
  import { u256 } from 'as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
3
  import { BytesWriter } from '../../buffer/BytesWriter';
4
- import { Address } from '../../types/Address';
4
+ import { Address, ADDRESS_BYTE_LENGTH } from '../../types/Address';
5
5
 
6
6
  @final
7
7
  export class MintEvent extends NetEvent {
8
8
  constructor(address: Address, amount: u256) {
9
- const data: BytesWriter = new BytesWriter(1, true);
9
+ const data: BytesWriter = new BytesWriter(32 + ADDRESS_BYTE_LENGTH);
10
10
  data.writeAddress(address);
11
11
  data.writeU256(amount);
12
12
 
@@ -5,7 +5,7 @@ import { BytesWriter } from '../../buffer/BytesWriter';
5
5
  @final
6
6
  export class StakeEvent extends NetEvent {
7
7
  constructor(amount: u256) {
8
- const data: BytesWriter = new BytesWriter(1, true);
8
+ const data: BytesWriter = new BytesWriter(32);
9
9
  data.writeU256(amount);
10
10
 
11
11
  super('Stake', data);
@@ -1,12 +1,12 @@
1
1
  import { u256 } from 'as-bignum/assembly';
2
2
  import { NetEvent } from '../NetEvent';
3
- import { Address } from '../../types/Address';
3
+ import { Address, ADDRESS_BYTE_LENGTH } from '../../types/Address';
4
4
  import { BytesWriter } from '../../buffer/BytesWriter';
5
5
 
6
6
  @final
7
7
  export class TransferEvent extends NetEvent {
8
8
  constructor(from: Address, to: Address, amount: u256) {
9
- const data: BytesWriter = new BytesWriter(1, true);
9
+ const data: BytesWriter = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + 32);
10
10
  data.writeAddress(from);
11
11
  data.writeAddress(to);
12
12
  data.writeU256(amount);
@@ -5,7 +5,7 @@ import { BytesWriter } from '../../buffer/BytesWriter';
5
5
  @final
6
6
  export class UnstakeEvent extends NetEvent {
7
7
  constructor(amount: u256) {
8
- const data: BytesWriter = new BytesWriter(1, true);
8
+ const data: BytesWriter = new BytesWriter(32);
9
9
  data.writeU256(amount);
10
10
 
11
11
  super('Unstake', data);
@@ -2,7 +2,7 @@ export function cyrb53(str: string, seed: i32 = 0): i64 {
2
2
  let h1: i32 = 0xdeadbeef ^ seed;
3
3
  let h2: i32 = 0x41c6ce57 ^ seed;
4
4
  for (let i: i32 = 0; i < str.length; i++) {
5
- let ch: i32 = str.charCodeAt(i);
5
+ const ch: i32 = str.charCodeAt(i);
6
6
  h1 = (h1 ^ ch) * 2654435761;
7
7
  h2 = (h2 ^ ch) * 1597334677;
8
8
  }
@@ -32,7 +32,7 @@ export function cyrb53a(str: u8[], seed: i32 = 0): u64 {
32
32
  let h2: u64 = u64(0x41c6ce57 ^ seed);
33
33
 
34
34
  for (let i: i32 = 0; i < str.length; i++) {
35
- let ch: u64 = u64(str[i]);
35
+ const ch: u64 = u64(str[i]);
36
36
  h1 = imul64(h1 ^ ch, 0x85ebca77);
37
37
  h2 = imul64(h2 ^ ch, 0xc2b2ae3d);
38
38
  }
@@ -42,5 +42,7 @@ export function cyrb53a(str: u8[], seed: i32 = 0): u64 {
42
42
  h1 ^= h2 >> 16;
43
43
  h2 ^= h1 >> 16;
44
44
 
45
+ // We are sure that the result is within the range of u64.
46
+ // eslint-disable-next-line no-loss-of-precision
45
47
  return (2097152 * (h2 & 0xffffffffffffffff) + (h1 >> 11)) & 0xffffffffffffffff;
46
48
  }
@@ -7,8 +7,10 @@ let random_seeded = false;
7
7
  function murmurHash3(h: u64): u64 {
8
8
  // Force all bits of a hash block to avalanche
9
9
  h ^= h >> 33; // see: https://github.com/aappleby/smhasher
10
+ // eslint-disable-next-line no-loss-of-precision
10
11
  h *= 0xff51afd7ed558ccd;
11
12
  h ^= h >> 33;
13
+ // eslint-disable-next-line no-loss-of-precision
12
14
  h *= 0xc4ceb9fe1a85ec53;
13
15
  h ^= h >> 33;
14
16
  return h;
@@ -25,6 +27,8 @@ function seedRandom(value: i64): void {
25
27
  // Instead zero seed use golden ratio:
26
28
  // phi = (1 + sqrt(5)) / 2
27
29
  // trunc(2^64 / phi) = 0x9e3779b97f4a7c15
30
+
31
+ // eslint-disable-next-line no-loss-of-precision
28
32
  if (value == 0) value = 0x9e3779b97f4a7c15;
29
33
  random_state0_64 = murmurHash3(value);
30
34
  random_state1_64 = murmurHash3(~random_state0_64);
@@ -40,7 +44,7 @@ function seedRandom(value: i64): void {
40
44
  export function randomU64(seed: i64): u64 {
41
45
  if (!random_seeded) seedRandom(seed);
42
46
  let s1 = random_state0_64;
43
- let s0 = random_state1_64;
47
+ const s0 = random_state1_64;
44
48
  random_state0_64 = s0;
45
49
  s1 ^= s1 << 23;
46
50
  s1 ^= s1 >> 17;
@@ -1,21 +1,21 @@
1
- import { Address } from '../types/Address';
2
- import { u256 } from 'as-bignum/assembly';
3
- import { BytesWriter } from '../buffer/BytesWriter';
4
- import { Blockchain } from '../env';
5
- import { encodeSelector, Selector } from '../math/abi';
6
-
7
- export class OP20Utils {
8
- public static get BALANCE_OF_SELECTOR(): Selector {
9
- return encodeSelector('balanceOf');
10
- }
11
-
12
- public static balanceOf(token: Address, owner: Address): u256 {
13
- const calldata: BytesWriter = new BytesWriter();
14
- calldata.writeSelector(OP20Utils.BALANCE_OF_SELECTOR);
15
- calldata.writeAddress(owner);
16
-
17
- const response = Blockchain.call(token, calldata);
18
-
19
- return response.readU256();
20
- }
21
- }
1
+ import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
2
+ import { u256 } from 'as-bignum/assembly';
3
+ import { BytesWriter } from '../buffer/BytesWriter';
4
+ import { Blockchain } from '../env';
5
+ import { encodeSelector, Selector } from '../math/abi';
6
+
7
+ export class OP20Utils {
8
+ public static get BALANCE_OF_SELECTOR(): Selector {
9
+ return encodeSelector('balanceOf');
10
+ }
11
+
12
+ public static balanceOf(token: Address, owner: Address): u256 {
13
+ const calldata: BytesWriter = new BytesWriter(4 + ADDRESS_BYTE_LENGTH);
14
+ calldata.writeSelector(OP20Utils.BALANCE_OF_SELECTOR);
15
+ calldata.writeAddress(owner);
16
+
17
+ const response = Blockchain.call(token, calldata);
18
+
19
+ return response.readU256();
20
+ }
21
+ }
@@ -1,6 +1,6 @@
1
1
  import { u256 } from 'as-bignum/assembly';
2
2
  import { encodeSelector, Selector } from '../math/abi';
3
- import { Address } from '../types/Address';
3
+ import { Address, ADDRESS_BYTE_LENGTH } from '../types/Address';
4
4
  import { BytesWriter } from '../buffer/BytesWriter';
5
5
  import { Blockchain } from '../env';
6
6
  import { Revert } from '../types/Revert';
@@ -19,7 +19,7 @@ export class TransferHelper {
19
19
  }
20
20
 
21
21
  public static safeApprove(token: Address, spender: Address, amount: u256): void {
22
- const calldata = new BytesWriter();
22
+ const calldata = new BytesWriter(4 + ADDRESS_BYTE_LENGTH + 32);
23
23
  calldata.writeSelector(this.APPROVE_SELECTOR);
24
24
  calldata.writeAddress(spender);
25
25
  calldata.writeU256(amount);
@@ -33,7 +33,7 @@ export class TransferHelper {
33
33
  }
34
34
 
35
35
  public static safeTransfer(token: Address, to: Address, amount: u256): void {
36
- const calldata = new BytesWriter();
36
+ const calldata = new BytesWriter(4 + ADDRESS_BYTE_LENGTH + 32);
37
37
  calldata.writeSelector(this.TRANSFER_SELECTOR);
38
38
  calldata.writeAddress(to);
39
39
  calldata.writeU256(amount);
@@ -47,7 +47,7 @@ export class TransferHelper {
47
47
  }
48
48
 
49
49
  public static safeTransferFrom(token: Address, from: Address, to: Address, amount: u256): void {
50
- const calldata = new BytesWriter();
50
+ const calldata = new BytesWriter(4 + ADDRESS_BYTE_LENGTH + ADDRESS_BYTE_LENGTH + 32);
51
51
  calldata.writeSelector(this.TRANSFER_FROM_SELECTOR);
52
52
 
53
53
  calldata.writeAddress(from);
@@ -1,79 +1,79 @@
1
- import { u256 } from 'as-bignum/assembly';
2
- import { Blockchain } from '../env';
3
- import { MemorySlotPointer } from '../memory/MemorySlotPointer';
4
- import { BytesWriter } from '../buffer/BytesWriter';
5
- import { BytesReader } from '../buffer/BytesReader';
6
- import { Revert } from '../types/Revert';
7
-
8
- export abstract class Serializable {
9
- protected pointer: u16;
10
- protected subPointer:MemorySlotPointer;
11
-
12
- protected constructor(pointer: u16,
13
- subPointer:MemorySlotPointer) {
14
- this.pointer = pointer;
15
- this.subPointer = subPointer;
16
- }
17
-
18
- public abstract get chunkCount(): i32;
19
- public abstract writeToBuffer(): BytesWriter;
20
- public abstract readFromBuffer(reader: BytesReader): void;
21
-
22
- public load() :void {
23
- const chunks: u256[] = [];
24
-
25
- for(let index:i32 = 0; index < this.chunkCount; index++){
26
- const chunk: u256 = Blockchain.getStorageAt(this.pointer, u256.add(this.subPointer, u256.fromU32(index)), u256.Zero);
27
- chunks.push(chunk);
28
- }
29
-
30
- const reader = this.chunksToBytes(chunks);
31
-
32
- this.readFromBuffer(reader);
33
- }
34
-
35
- public save(): void {
36
- const writer: BytesWriter = this.writeToBuffer();
37
-
38
- const buffer = writer.getBuffer();
39
-
40
- const chunks: u256[] = this.bytesToChunks(buffer);
41
-
42
- for (let index: i32 = 0; index < chunks.length; index++) {
43
- Blockchain.setStorageAt(
44
- this.pointer,
45
- u256.add(this.subPointer, u256.fromU32(index)),
46
- chunks[index],
47
- );
48
- }
49
- }
50
-
51
- protected bytesToChunks(buffer: Uint8Array): u256[] {
52
- const chunks: u256[] = [];
53
-
54
- for (let index: i32 = 0; index < buffer.byteLength; index += 32) {
55
- const chunk = buffer.slice(index, index + 32);
56
- chunks.push(u256.fromBytes(chunk, true));
57
- }
58
-
59
- return chunks;
60
- }
61
-
62
- protected chunksToBytes(chunks: u256[]): BytesReader {
63
- if(this.chunkCount >= 67108863) {
64
- throw new Revert('Too many chunks received');
65
- }
66
-
67
- const buffer: Uint8Array = new Uint8Array(this.chunkCount * 32);
68
- let offset: i32 = 0;
69
-
70
- for (let indexChunk: i32 = 0; indexChunk < chunks.length; indexChunk++) {
71
- const bytes: u8[] = chunks[indexChunk].toBytes(true);
72
- for (let indexByte: i32 = 0; indexByte < bytes.length; indexByte++) {
73
- buffer[offset++] = bytes[indexByte];
74
- }
75
- }
76
-
77
- return new BytesReader(buffer);
78
- }
79
- }
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { Blockchain } from '../env';
3
+ import { MemorySlotPointer } from '../memory/MemorySlotPointer';
4
+ import { BytesWriter } from '../buffer/BytesWriter';
5
+ import { BytesReader } from '../buffer/BytesReader';
6
+ import { Revert } from '../types/Revert';
7
+
8
+ export abstract class Serializable {
9
+ protected pointer: u16;
10
+ protected subPointer:MemorySlotPointer;
11
+
12
+ protected constructor(pointer: u16,
13
+ subPointer:MemorySlotPointer) {
14
+ this.pointer = pointer;
15
+ this.subPointer = subPointer;
16
+ }
17
+
18
+ public abstract get chunkCount(): i32;
19
+ public abstract writeToBuffer(): BytesWriter;
20
+ public abstract readFromBuffer(reader: BytesReader): void;
21
+
22
+ public load() :void {
23
+ const chunks: u256[] = [];
24
+
25
+ for(let index:i32 = 0; index < this.chunkCount; index++){
26
+ const chunk: u256 = Blockchain.getStorageAt(this.pointer, u256.add(this.subPointer, u256.fromU32(index)), u256.Zero);
27
+ chunks.push(chunk);
28
+ }
29
+
30
+ const reader = this.chunksToBytes(chunks);
31
+
32
+ this.readFromBuffer(reader);
33
+ }
34
+
35
+ public save(): void {
36
+ const writer: BytesWriter = this.writeToBuffer();
37
+
38
+ const buffer = writer.getBuffer();
39
+
40
+ const chunks: u256[] = this.bytesToChunks(buffer);
41
+
42
+ for (let index: i32 = 0; index < chunks.length; index++) {
43
+ Blockchain.setStorageAt(
44
+ this.pointer,
45
+ u256.add(this.subPointer, u256.fromU32(index)),
46
+ chunks[index],
47
+ );
48
+ }
49
+ }
50
+
51
+ protected bytesToChunks(buffer: Uint8Array): u256[] {
52
+ const chunks: u256[] = [];
53
+
54
+ for (let index: i32 = 0; index < buffer.byteLength; index += 32) {
55
+ const chunk = buffer.slice(index, index + 32);
56
+ chunks.push(u256.fromBytes(chunk, true));
57
+ }
58
+
59
+ return chunks;
60
+ }
61
+
62
+ protected chunksToBytes(chunks: u256[]): BytesReader {
63
+ if(this.chunkCount >= 67108863) {
64
+ throw new Revert('Too many chunks received');
65
+ }
66
+
67
+ const buffer: Uint8Array = new Uint8Array(this.chunkCount * 32);
68
+ let offset: i32 = 0;
69
+
70
+ for (let indexChunk: i32 = 0; indexChunk < chunks.length; indexChunk++) {
71
+ const bytes: u8[] = chunks[indexChunk].toBytes(true);
72
+ for (let indexByte: i32 = 0; indexByte < bytes.length; indexByte++) {
73
+ buffer[offset++] = bytes[indexByte];
74
+ }
75
+ }
76
+
77
+ return new BytesReader(buffer);
78
+ }
79
+ }
@@ -63,7 +63,7 @@ export class StoredString {
63
63
  // Save the remaining chunks in subsequent storage slots
64
64
  while (remainingLength > 0) {
65
65
  bytesToWrite = this.min(remainingLength, 32);
66
- let storageValue: u256 = this.saveChunk(
66
+ const storageValue: u256 = this.saveChunk(
67
67
  u256.Zero,
68
68
  this._value,
69
69
  offset,
@@ -86,9 +86,9 @@ export class StoredString {
86
86
  length: u32,
87
87
  storageOffset: u32,
88
88
  ): u256 {
89
- let bytes = storage.toBytes(true);
89
+ const bytes = storage.toBytes(true);
90
90
  for (let i: u32 = 0; i < length; i++) {
91
- let index: i32 = i32(offset + i);
91
+ const index: i32 = i32(offset + i);
92
92
  bytes[i + storageOffset] = u8(value.charCodeAt(index));
93
93
  }
94
94
  return u256.fromBytes(bytes, true);
@@ -113,7 +113,7 @@ export class StoredString {
113
113
  let remainingLength: u32 = length;
114
114
  let currentStorage: u256 = header;
115
115
 
116
- let bytesToRead: u32 = this.min(remainingLength, 28);
116
+ const bytesToRead: u32 = this.min(remainingLength, 28);
117
117
  let str: string = this.loadChunk(currentStorage, 4, bytesToRead);
118
118
  remainingLength -= bytesToRead;
119
119
 
@@ -123,7 +123,7 @@ export class StoredString {
123
123
  currentStorage = Blockchain.getStorageAt(this.pointer, currentPointer, u256.Zero);
124
124
 
125
125
  // Extract the relevant portion of the string from the current storage slot
126
- let bytesToRead: u32 = this.min(remainingLength, 32);
126
+ const bytesToRead: u32 = this.min(remainingLength, 32);
127
127
  str += this.loadChunk(currentStorage, 0, bytesToRead);
128
128
 
129
129
  remainingLength -= bytesToRead;