@btc-vision/btc-runtime 1.2.6 → 1.3.0

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 (34) hide show
  1. package/README.md +73 -37
  2. package/package.json +7 -4
  3. package/runtime/buffer/BytesReader.ts +11 -6
  4. package/runtime/buffer/BytesWriter.ts +9 -17
  5. package/runtime/contracts/DeployableOP_20.ts +4 -16
  6. package/runtime/contracts/OP_NET.ts +2 -2
  7. package/runtime/contracts/interfaces/IOP_20.ts +0 -2
  8. package/runtime/env/BlockchainEnvironment.ts +13 -10
  9. package/runtime/generic/AddressMap.ts +62 -0
  10. package/runtime/generic/Map.ts +9 -8
  11. package/runtime/index.ts +18 -4
  12. package/runtime/memory/AddressMemoryMap.ts +8 -7
  13. package/runtime/memory/MultiAddressMemoryMap.ts +7 -7
  14. package/runtime/memory/MultiStringMemoryMap.ts +62 -0
  15. package/runtime/memory/StringMemoryMap.ts +57 -0
  16. package/runtime/memory/Uint8ArrayMerger.ts +67 -0
  17. package/runtime/secp256k1/ECPoint.ts +121 -0
  18. package/runtime/storage/StorageBacked.ts +5 -0
  19. package/runtime/storage/StorageLayout.ts +7 -0
  20. package/runtime/storage/StorageSlot.ts +106 -0
  21. package/runtime/storage/StorageStruct.ts +23 -0
  22. package/runtime/storage/StorageValue.ts +36 -0
  23. package/runtime/storage/StoredAddress.ts +47 -0
  24. package/runtime/storage/StoredU256.ts +5 -0
  25. package/runtime/tests/assert.ts +6 -3
  26. package/runtime/tests/env.ts +2 -2
  27. package/runtime/tests/tests.ts +18 -16
  28. package/runtime/types/Address.ts +121 -2
  29. package/runtime/types/SafeMath.ts +24 -0
  30. package/runtime/utils/b32.ts +243 -0
  31. package/runtime/utils/box.ts +126 -107
  32. package/runtime/utils/encodings.ts +46 -0
  33. package/runtime/utils/hex.ts +50 -47
  34. package/runtime/utils/index.ts +3 -2
@@ -1,13 +1,13 @@
1
1
  import { MemorySlotData } from './MemorySlot';
2
2
  import { u256 } from 'as-bignum/assembly';
3
- import { KeyMerger } from './KeyMerger';
3
+ import { Uint8ArrayMerger } from './Uint8ArrayMerger';
4
4
 
5
5
  @final
6
6
  export class MultiAddressMemoryMap<
7
- K extends string,
8
- K2 extends string,
7
+ K extends Uint8Array,
8
+ K2 extends Uint8Array,
9
9
  V extends MemorySlotData<u256>,
10
- > extends Map<K, KeyMerger<K, K2, V>> {
10
+ > extends Map<K, Uint8ArrayMerger<V>> {
11
11
  public pointer: u16;
12
12
 
13
13
  constructor(
@@ -19,7 +19,7 @@ export class MultiAddressMemoryMap<
19
19
  this.pointer = pointer;
20
20
  }
21
21
 
22
- public get(key: K): KeyMerger<K, K2, V> {
22
+ public get(key: K): Uint8ArrayMerger<V> {
23
23
  this.createKeyMerger(key);
24
24
 
25
25
  return super.get(key);
@@ -36,7 +36,7 @@ export class MultiAddressMemoryMap<
36
36
  return this;
37
37
  }
38
38
 
39
- public set(key: K, value: KeyMerger<K, K2, V>): this {
39
+ public set(key: K, value: Uint8ArrayMerger<V>): this {
40
40
  this.createKeyMerger(key);
41
41
 
42
42
  return <this>super.set(key, value);
@@ -56,7 +56,7 @@ export class MultiAddressMemoryMap<
56
56
 
57
57
  private createKeyMerger(key: K): void {
58
58
  if (!super.has(key)) {
59
- super.set(key, new KeyMerger<K, K2, V>(key, this.pointer, this.defaultValue));
59
+ super.set(key, new Uint8ArrayMerger<V>(key, this.pointer, this.defaultValue));
60
60
  }
61
61
  }
62
62
  }
@@ -0,0 +1,62 @@
1
+ import { MemorySlotData } from './MemorySlot';
2
+ import { u256 } from 'as-bignum/assembly';
3
+ import { KeyMerger } from './KeyMerger';
4
+
5
+ @final
6
+ export class MultiStringMemoryMap<
7
+ K extends string,
8
+ K2 extends string,
9
+ V extends MemorySlotData<u256>,
10
+ > extends Map<K, KeyMerger<K, K2, V>> {
11
+ public pointer: u16;
12
+
13
+ constructor(
14
+ pointer: u16,
15
+ private readonly defaultValue: V,
16
+ ) {
17
+ super();
18
+
19
+ this.pointer = pointer;
20
+ }
21
+
22
+ public get(key: K): KeyMerger<K, K2, V> {
23
+ this.createKeyMerger(key);
24
+
25
+ return super.get(key);
26
+ }
27
+
28
+ public setUpperKey(key: K, key2: K2, value: V): this {
29
+ this.createKeyMerger(key);
30
+
31
+ const subMap = super.get(key);
32
+ if (subMap) {
33
+ subMap.set(key2, value);
34
+ }
35
+
36
+ return this;
37
+ }
38
+
39
+ public set(key: K, value: KeyMerger<K, K2, V>): this {
40
+ this.createKeyMerger(key);
41
+
42
+ return <this>super.set(key, value);
43
+ }
44
+
45
+ public has(key: K): bool {
46
+ return super.has(key);
47
+ }
48
+
49
+ public delete(key: K): bool {
50
+ return super.delete(key);
51
+ }
52
+
53
+ public clear(): void {
54
+ super.clear();
55
+ }
56
+
57
+ private createKeyMerger(key: K): void {
58
+ if (!super.has(key)) {
59
+ super.set(key, new KeyMerger<K, K2, V>(key, this.pointer, this.defaultValue));
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,57 @@
1
+ import { MemorySlotPointer } from './MemorySlotPointer';
2
+ import { Blockchain } from '../env';
3
+ import { encodePointer } from '../math/abi';
4
+ import { MemorySlotData } from './MemorySlot';
5
+ import { u256 } from 'as-bignum/assembly';
6
+ import { BytesWriter } from '../buffer/BytesWriter';
7
+
8
+ @final
9
+ export class StringMemoryMap<K extends string, V extends MemorySlotData<u256>> {
10
+ public pointer: u16;
11
+
12
+ constructor(
13
+ pointer: u16,
14
+ private readonly defaultValue: V,
15
+ ) {
16
+ this.pointer = pointer;
17
+ }
18
+
19
+ public set(key: K, value: V): this {
20
+ const keyHash: MemorySlotPointer = this.encodePointer(key);
21
+ Blockchain.setStorageAt(keyHash, value);
22
+
23
+ return this;
24
+ }
25
+
26
+ public get(key: K): MemorySlotData<u256> {
27
+ const keyHash: MemorySlotPointer = this.encodePointer(key);
28
+
29
+ return Blockchain.getStorageAt(keyHash, this.defaultValue);
30
+ }
31
+
32
+ public has(key: K): bool {
33
+ const keyHash: MemorySlotPointer = this.encodePointer(key);
34
+
35
+ return Blockchain.hasStorageAt(keyHash);
36
+ }
37
+
38
+ @unsafe
39
+ public delete(key: K): bool {
40
+ this.set(key, this.defaultValue);
41
+
42
+ return true;
43
+ }
44
+
45
+ @unsafe
46
+ public clear(): void {
47
+ throw new Error('Method not implemented.');
48
+ }
49
+
50
+ private encodePointer(key: K): MemorySlotPointer {
51
+ const writer = new BytesWriter(key.length + 2);
52
+ writer.writeU16(this.pointer);
53
+ writer.writeString(key);
54
+
55
+ return encodePointer(writer.getBuffer());
56
+ }
57
+ }
@@ -0,0 +1,67 @@
1
+ import { MemorySlotData } from './MemorySlot';
2
+ import { u256 } from 'as-bignum/assembly';
3
+ import { Blockchain } from '../env';
4
+ import { MemorySlotPointer } from './MemorySlotPointer';
5
+ import { encodePointer } from '../math/abi';
6
+ import { BytesWriter } from '../buffer/BytesWriter';
7
+
8
+ @final
9
+ export class Uint8ArrayMerger<V extends MemorySlotData<u256>> {
10
+ public parentKey: Uint8Array;
11
+
12
+ public pointer: u16;
13
+
14
+ constructor(
15
+ parent: Uint8Array,
16
+ pointer: u16,
17
+ private readonly defaultValue: V,
18
+ ) {
19
+ this.pointer = pointer;
20
+
21
+ this.parentKey = parent;
22
+ }
23
+
24
+ public set(key: Uint8Array, value: V): this {
25
+ const keyHash: MemorySlotPointer = this.getKeyHash(key);
26
+ Blockchain.setStorageAt(keyHash, value);
27
+
28
+ return this;
29
+ }
30
+
31
+ public get(key: Uint8Array): MemorySlotData<u256> {
32
+ const keyHash: MemorySlotPointer = this.getKeyHash(key);
33
+
34
+ return Blockchain.getStorageAt(keyHash, this.defaultValue);
35
+ }
36
+
37
+ public has(key: Uint8Array): bool {
38
+ const mergedKey: MemorySlotPointer = this.getKeyHash(key);
39
+
40
+ return Blockchain.hasStorageAt(mergedKey);
41
+ }
42
+
43
+ @unsafe
44
+ public delete(_key: Uint8Array): bool {
45
+ throw new Error('Method not implemented.');
46
+ }
47
+
48
+ @unsafe
49
+ public clear(): void {
50
+ throw new Error('Clear method not implemented.');
51
+ }
52
+
53
+ private getKeyHash(key: Uint8Array): MemorySlotPointer {
54
+ const writer: BytesWriter = new BytesWriter(key.byteLength + 2 + this.parentKey.byteLength);
55
+
56
+ writer.writeBytes(this.parentKey);
57
+ writer.writeBytes(key);
58
+
59
+ return this.encodePointer(writer);
60
+ }
61
+
62
+ private encodePointer(writer: BytesWriter): MemorySlotPointer {
63
+ writer.writeU16(this.pointer);
64
+
65
+ return encodePointer(writer.getBuffer());
66
+ }
67
+ }
@@ -0,0 +1,121 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { SafeMath } from '../types/SafeMath';
3
+
4
+ // secp256k1 curve parameters (using little-endian byte arrays)
5
+ const P_BYTES: u8[] = [
6
+ 0x2f, 0xfc, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
7
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
8
+ ]; // P in little-endian
9
+
10
+ const GX_BYTES: u8[] = [
11
+ 0x98, 0x17, 0xf8, 0x16, 0xb1, 0x5b, 0x28, 0xd9, 0x59, 0x28, 0xce, 0x2d, 0xdb, 0xfc, 0x9b, 0x02,
12
+ 0x70, 0xb0, 0x87, 0xce, 0x95, 0xa0, 0x62, 0x55, 0xac, 0xbb, 0xdc, 0xf9, 0xef, 0x66, 0xbe, 0x79,
13
+ ]; // Gx in little-endian
14
+
15
+ const GY_BYTES: u8[] = [
16
+ 0xb8, 0xd4, 0x10, 0xfb, 0xff, 0x08, 0x7d, 0xc4, 0x19, 0x54, 0x85, 0xa6, 0x48, 0x44, 0x17, 0xfd,
17
+ 0xa8, 0x08, 0xe1, 0x0e, 0xfc, 0x4b, 0xa4, 0x5d, 0x65, 0xc4, 0xa3, 0xa6, 0x77, 0xda, 0x3a, 0x48,
18
+ ]; // Gy in little-endian
19
+
20
+ // Converting byte arrays to u256 using fromBytesLe (little-endian)
21
+ const P = u256.fromBytesLE(P_BYTES);
22
+ const GX = u256.fromBytesLE(GX_BYTES);
23
+ const GY = u256.fromBytesLE(GY_BYTES);
24
+
25
+ // Define a point on the elliptic curve
26
+ class ECPoint {
27
+ x: u256;
28
+ y: u256;
29
+
30
+ constructor(x: u256, y: u256) {
31
+ this.x = x;
32
+ this.y = y;
33
+ }
34
+
35
+ // Point doubling: P + P = 2P
36
+ static double(p: ECPoint): ECPoint {
37
+ if (p.y == u256.Zero) {
38
+ return new ECPoint(u256.Zero, u256.Zero); // Point at infinity
39
+ }
40
+
41
+ const two = u256.fromU64(2);
42
+ const three = u256.fromU64(3);
43
+
44
+ // lambda = (3 * p.x^2) / (2 * p.y) mod P
45
+ const numerator = SafeMath.mod(SafeMath.mul(three, SafeMath.pow(p.x, two)), P);
46
+ const denominator = SafeMath.modInverse(SafeMath.mul(two, p.y), P);
47
+ const lambda = SafeMath.mod(SafeMath.mul(numerator, denominator), P);
48
+
49
+ // xr = lambda^2 - 2 * p.x mod P
50
+ const xr = SafeMath.mod(SafeMath.sub(SafeMath.pow(lambda, two), SafeMath.mul(two, p.x)), P);
51
+
52
+ // yr = lambda * (p.x - xr) - p.y mod P
53
+ const yr = SafeMath.mod(SafeMath.sub(SafeMath.mul(lambda, SafeMath.sub(p.x, xr)), p.y), P);
54
+
55
+ return new ECPoint(xr, yr);
56
+ }
57
+
58
+ // Point addition: P + Q = R
59
+ static add(p: ECPoint, q: ECPoint): ECPoint {
60
+ if (p.x == q.x && p.y == q.y) {
61
+ return this.double(p); // If P == Q, perform doubling
62
+ }
63
+
64
+ const lambda = SafeMath.mod(
65
+ SafeMath.mul(SafeMath.sub(q.y, p.y), SafeMath.modInverse(SafeMath.sub(q.x, p.x), P)),
66
+ P,
67
+ );
68
+ const xr = SafeMath.mod(
69
+ SafeMath.sub(SafeMath.pow(lambda, u256.fromU64(2)), SafeMath.add(p.x, q.x)),
70
+ P,
71
+ );
72
+ const yr = SafeMath.mod(SafeMath.sub(SafeMath.mul(lambda, SafeMath.sub(p.x, xr)), p.y), P);
73
+
74
+ return new ECPoint(xr, yr);
75
+ }
76
+
77
+ // Scalar multiplication: k * P
78
+ static scalarMultiply(p: ECPoint, k: u256): ECPoint {
79
+ let result = new ECPoint(u256.Zero, u256.Zero); // Point at infinity
80
+ let addend = p;
81
+
82
+ while (!k.isZero()) {
83
+ if (!SafeMath.isEven(k)) {
84
+ result = this.add(result, addend);
85
+ }
86
+ addend = this.double(addend);
87
+ k = SafeMath.div(k, u256.fromU64(2)); // Right shift by 1
88
+ }
89
+
90
+ return result;
91
+ }
92
+ }
93
+
94
+ // Generate a valid elliptic curve point (public key) from a hash
95
+ export function generatePublicKeyFromHash(scalar: u256): u8[] {
96
+ // Convert hash to u256 scalar
97
+ //const scalar = u256.fromBytes(hash);
98
+
99
+ // Define the generator point on secp256k1 curve
100
+ const G = new ECPoint(GX, GY);
101
+
102
+ // Perform scalar multiplication to get public key point
103
+ const publicKeyPoint = ECPoint.scalarMultiply(G, scalar);
104
+
105
+ // Convert the point to bytes (compressed format)
106
+ return pointToBytes(publicKeyPoint);
107
+ }
108
+
109
+ // Convert elliptic curve point to compressed byte array
110
+ function pointToBytes(point: ECPoint): u8[] {
111
+ const prefix: u8 = SafeMath.isEven(point.y) ? 0x02 : 0x03; // Compressed format prefix
112
+ const xBytes = point.x.toUint8Array(); // Convert X coordinate to bytes
113
+
114
+ const result = new Array<u8>(33); // 1 byte prefix + 32 bytes X coordinate
115
+ result[0] = prefix;
116
+ for (let i = 0; i < 32; i++) {
117
+ result[i + 1] = xBytes[i];
118
+ }
119
+
120
+ return result;
121
+ }
@@ -0,0 +1,5 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+
3
+ export interface StorageBacked {
4
+ serialize(): Array<u256>;
5
+ }
@@ -0,0 +1,7 @@
1
+ import { Blockchain } from '../env';
2
+
3
+ export class StorageLayout {
4
+ public next(): u16 {
5
+ return Blockchain.nextPointer;
6
+ }
7
+ }
@@ -0,0 +1,106 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { BlockchainEnvironment } from '../env/BlockchainEnvironment';
3
+ import { Sha256 } from '../math/sha256';
4
+ import { MemorySlotPointer } from '../memory/MemorySlotPointer';
5
+ import { Box, concat, fromArrayBuffer, toArrayBuffer } from '../utils';
6
+
7
+ export function toBuffer<T>(v: T): ArrayBuffer {
8
+ const result = new ArrayBuffer(sizeof<T>());
9
+ store<T>(changetype<usize>(result), v);
10
+ return result;
11
+ }
12
+
13
+ export class StorageSlot {
14
+ public pointer: u16;
15
+ public subPointer: MemorySlotPointer;
16
+
17
+ constructor(pointer: u16, subPointer: MemorySlotPointer) {
18
+ this.pointer = pointer;
19
+ this.subPointer = subPointer;
20
+ }
21
+
22
+ public get pointerHash(): u256 {
23
+ return fromArrayBuffer(
24
+ Sha256.hash(
25
+ Uint8Array.wrap(
26
+ Box.concat([
27
+ Box.from(toBuffer(this.pointer)),
28
+ Box.from(toArrayBuffer(this.subPointer)),
29
+ ]),
30
+ ),
31
+ ),
32
+ );
33
+ }
34
+
35
+ public static wrap(v: ArrayBuffer): StorageSlot {
36
+ return new StorageSlot(0, fromArrayBuffer(Sha256.hash(Uint8Array.wrap(v))));
37
+ }
38
+
39
+ public static for(keyword: string): StorageSlot {
40
+ return StorageSlot.wrap(String.UTF8.encode(keyword));
41
+ }
42
+
43
+ public static at(pointer: u16): StorageSlot {
44
+ return new StorageSlot(pointer, u256.Zero);
45
+ }
46
+
47
+ public select(v: ArrayBuffer): StorageSlot {
48
+ return new StorageSlot(
49
+ this.pointer,
50
+ fromArrayBuffer(
51
+ Sha256.hash(
52
+ Uint8Array.wrap(
53
+ concat(toArrayBuffer(this.subPointer), Sha256.hash(Uint8Array.wrap(v))),
54
+ ),
55
+ ),
56
+ ),
57
+ );
58
+ }
59
+
60
+ public keyword(key: string): StorageSlot {
61
+ return this.select(String.UTF8.encode(key));
62
+ }
63
+
64
+ public get(): u256 {
65
+ return changetype<BlockchainEnvironment>(0).getStorageAt(this.pointerHash, u256.Zero);
66
+ }
67
+
68
+ public set(v: u256): void {
69
+ changetype<BlockchainEnvironment>(0).setStorageAt(this.pointerHash, v);
70
+ }
71
+
72
+ public lengthKey(): StorageSlot {
73
+ return this.keyword('/length');
74
+ }
75
+
76
+ public length(): u32 {
77
+ return this.lengthKey().get().toU32();
78
+ }
79
+
80
+ public getList(): Array<u256> {
81
+ const result = new Array<u256>(<i32>this.length());
82
+ for (let i: i32 = 0; i < result.length; i++) {
83
+ result[i] = this.selectIndex(i).get();
84
+ }
85
+ return result;
86
+ }
87
+
88
+ public extend(): StorageSlot {
89
+ const lengthKey = this.lengthKey();
90
+ const length = lengthKey.get().toU32();
91
+ lengthKey.set(u256.from(length + 1));
92
+ return this.selectIndex(length);
93
+ }
94
+
95
+ public selectIndex(index: u32): StorageSlot {
96
+ return this.keyword('/' + index.toString(10));
97
+ }
98
+
99
+ public nullify(): void {
100
+ this.set(u256.Zero);
101
+ }
102
+
103
+ public append(v: u256): void {
104
+ this.extend().set(v);
105
+ }
106
+ }
@@ -0,0 +1,23 @@
1
+ import { StorageSlot } from './StorageSlot';
2
+ import { StorageBacked } from './StorageBacked';
3
+
4
+ export class StorageStruct<T extends StorageBacked> {
5
+ public inner: T;
6
+ public slot: StorageSlot;
7
+
8
+ constructor(slot: StorageSlot, inner: T) {
9
+ this.slot = slot;
10
+ this.inner = inner;
11
+ }
12
+
13
+ public static load<T extends StorageBacked>(slot: StorageSlot): StorageStruct<T> {
14
+ return new StorageStruct<T>(slot, instantiate<T>(slot.getList()));
15
+ }
16
+
17
+ public save(): void {
18
+ const packed = this.inner.serialize();
19
+ for (let i = 0; i < packed.length; i++) {
20
+ this.slot.selectIndex(i).set(packed[i]);
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,36 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { StorageSlot } from './StorageSlot';
3
+
4
+ export class StorageValue<T> {
5
+ public value: u256;
6
+ public slot: StorageSlot;
7
+
8
+ constructor(slot: StorageSlot) {
9
+ this.slot = slot;
10
+ this.value = u256.Zero;
11
+ }
12
+
13
+ public static at<T>(slot: StorageSlot): StorageValue<T> {
14
+ return new StorageValue<T>(slot);
15
+ }
16
+
17
+ public save(): this {
18
+ this.slot.set(u256.from(this.value));
19
+ return this;
20
+ }
21
+
22
+ public set(v: T): this {
23
+ this.value = u256.from(v);
24
+ this.save();
25
+ return this;
26
+ }
27
+
28
+ public load(): this {
29
+ this.value = this.slot.get();
30
+ return this;
31
+ }
32
+
33
+ public unwrap(): T {
34
+ return load<T>(changetype<usize>(this.value.toUint8Array().buffer));
35
+ }
36
+ }
@@ -0,0 +1,47 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { Blockchain } from '../env';
3
+ import { encodePointer } from '../math/abi';
4
+ import { BytesWriter } from '../buffer/BytesWriter';
5
+ import { Address } from '../types/Address';
6
+
7
+ @final
8
+ export class StoredAddress {
9
+ private readonly addressPointer: u256;
10
+ private readonly defaultValue: u256;
11
+
12
+ constructor(
13
+ public pointer: u16,
14
+ defaultValue: Address,
15
+ ) {
16
+ const writer = new BytesWriter(32);
17
+ writer.writeU16(pointer);
18
+
19
+ this.defaultValue = u256.fromBytes(defaultValue);
20
+ this.addressPointer = encodePointer(writer.getBuffer());
21
+ }
22
+
23
+ private _value: Address = new Address();
24
+
25
+ @inline
26
+ public get value(): Address {
27
+ this.ensureValue();
28
+
29
+ return this._value;
30
+ }
31
+
32
+ @inline
33
+ public set value(value: Address) {
34
+ if (value === this.value) {
35
+ return;
36
+ }
37
+
38
+ this._value = value;
39
+
40
+ Blockchain.setStorageAt(this.addressPointer, u256.fromBytes(this._value));
41
+ }
42
+
43
+ private ensureValue(): void {
44
+ const value = Blockchain.getStorageAt(this.addressPointer, this.defaultValue);
45
+ this._value.set(value.toBytes());
46
+ }
47
+ }
@@ -46,6 +46,11 @@ export class StoredU256 {
46
46
  return this._value.toUint8Array(false);
47
47
  }
48
48
 
49
+ @inline
50
+ public toString(): string {
51
+ return this._value.toString();
52
+ }
53
+
49
54
  @inline
50
55
  @operator('+')
51
56
  public add(value: u256): this {
@@ -1,8 +1,11 @@
1
1
  export function assert(condition: boolean, e: string): void {
2
- if (!condition) throw new Error(e);
2
+ if (!condition) throw new Error(e);
3
3
  }
4
4
 
5
- export function assertEq<T>(a: T, b: T): void {
6
- assert(a === b, "expected " + a.toString() + " to equal " + b.toString());
5
+ interface WithToString {
6
+ toString(): string;
7
7
  }
8
8
 
9
+ export function assertEq<T extends WithToString>(a: T, b: T): void {
10
+ assert(a === b, 'expected ' + a.toString() + ' to equal ' + b.toString());
11
+ }
@@ -1,7 +1,7 @@
1
1
  // @ts-ignore
2
- @external("env", "logStatic")
2
+ @external('env', 'logStatic')
3
3
  export declare function __logStatic(ptr: ArrayBuffer): void;
4
4
 
5
5
  export function log(v: string): void {
6
- return __logStatic(String.UTF8.encode(v));
6
+ return __logStatic(String.UTF8.encode(v));
7
7
  }
@@ -1,25 +1,27 @@
1
- import { BytesWriter } from "../buffer/BytesWriter";
2
- import { u256 } from "as-bignum/assembly";
3
- import { Blockchain } from "../env";
4
- import { Box } from "../utils/box";
5
- import { log } from "./env";
6
- import { assertEq } from "./assert";
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { BytesWriter } from '../buffer/BytesWriter';
3
+ import { Blockchain } from '../env';
4
+ import { Box } from '../utils/box';
5
+ import { assertEq } from './assert';
7
6
 
8
7
  export function test_encode(): void {
9
- const writer = new BytesWriter(64);
10
- writer.writeU256(u256.from(10));
11
- writer.writeU256(u256.from(20));
12
- const buffer = writer.getBuffer().buffer;
13
- assertEq(Box.from(buffer).toHexString(), "0x0a000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000");
8
+ const writer = new BytesWriter(64);
9
+ writer.writeU256(u256.from(10));
10
+ writer.writeU256(u256.from(20));
11
+ const buffer = writer.getBuffer().buffer;
12
+ assertEq(
13
+ Box.from(buffer).toHexString(),
14
+ '0x000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000014',
15
+ );
14
16
  }
15
17
 
16
18
  export function test_log(): void {
17
- Blockchain.log("test logging test: OK!");
19
+ Blockchain.log('test logging test: OK!');
18
20
  }
19
21
 
20
22
  export function test_writeStringWithLength(): void {
21
- const s = 'test write';
22
- const writer = new BytesWriter(s.length + 2);
23
- writer.writeStringWithLength(s);
24
- assertEq(Box.from(writer.getBuffer().buffer).toHexString(), "0x0a0074657374207772697465");
23
+ const s = 'test write';
24
+ const writer = new BytesWriter(s.length + 2);
25
+ writer.writeStringWithLength(s);
26
+ assertEq(Box.from(writer.getBuffer().buffer).toHexString(), '0x0a0074657374207772697465');
25
27
  }