@btc-vision/btc-runtime 1.0.11 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,8 +11,8 @@
11
11
 
12
12
  ## Introduction
13
13
 
14
- The OPNet Smart Contract Runtime is a WebAssembly runtime that is designed to help developers write smart contracts for the OPNet blockchain.
15
- The runtime is written in AssemblyScript, a subset of TypeScript that compiles to WebAssembly.
14
+ The OPNet Smart Contract Runtime contains all the necessary components to effectively create smart contracts on Bitcoin
15
+ L1. The runtime is written in AssemblyScript.
16
16
 
17
17
  ### Installation
18
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.0.11",
3
+ "version": "1.0.14",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "types": "btc/index.ts",
@@ -299,7 +299,7 @@ export class BytesWriter {
299
299
 
300
300
  private fromAddress(value: Address): Uint8Array {
301
301
  if (value.length > i32(ADDRESS_BYTE_LENGTH)) {
302
- throw new Revert('Address is too long');
302
+ throw new Revert(`Address is too long ${value.length} > ${ADDRESS_BYTE_LENGTH} bytes`);
303
303
  }
304
304
 
305
305
  const bytes: Uint8Array = new Uint8Array(ADDRESS_BYTE_LENGTH);
@@ -23,29 +23,28 @@ const transferSelector = encodeSelector('transfer');
23
23
  const transferFromSelector = encodeSelector('transferFrom');
24
24
 
25
25
  export abstract class OP_20 extends OP_NET implements IOP_20 {
26
- public readonly decimals: u8 = 8;
27
-
28
- public readonly name: string = `OP_20`;
29
- public readonly symbol: string = `OP`;
30
-
31
26
  protected readonly allowanceMap: MultiAddressMemoryMap<Address, Address, MemorySlotData<u256>>;
32
27
  protected readonly balanceOfMap: AddressMemoryMap<Address, MemorySlotData<u256>>;
33
28
 
34
- protected constructor(public readonly maxSupply: u256) {
29
+ protected constructor(
30
+ protected readonly maxSupply: u256,
31
+ protected readonly decimals: u8,
32
+ protected readonly name: string,
33
+ protected readonly symbol: string,
34
+ ) {
35
35
  super();
36
36
 
37
37
  this.allowanceMap = new MultiAddressMemoryMap<Address, Address, MemorySlotData<u256>>(
38
38
  Blockchain.nextPointer,
39
39
  u256.Zero,
40
40
  );
41
+
41
42
  this.balanceOfMap = new AddressMemoryMap<Address, MemorySlotData<u256>>(
42
43
  Blockchain.nextPointer,
43
44
  u256.Zero,
44
45
  );
45
46
 
46
- const supplyPointer = Blockchain.nextPointer;
47
- const supply: u256 = Blockchain.getStorageAt(supplyPointer, u256.Zero, u256.Zero);
48
- this._totalSupply = new StoredU256(supplyPointer, u256.Zero, supply);
47
+ this._totalSupply = new StoredU256(Blockchain.nextPointer, u256.Zero, u256.Zero);
49
48
  }
50
49
 
51
50
  public _totalSupply: StoredU256;
@@ -156,10 +155,10 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
156
155
  response.writeU8(this.decimals);
157
156
  break;
158
157
  case encodeSelector('name'):
159
- response.writeString(this.name);
158
+ response.writeStringWithLength(this.name);
160
159
  break;
161
160
  case encodeSelector('symbol'):
162
- response.writeString(this.symbol);
161
+ response.writeStringWithLength(this.symbol);
163
162
  break;
164
163
  case encodeSelector('totalSupply'):
165
164
  response.writeU256(this.totalSupply);
@@ -229,9 +228,7 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
229
228
  const caller = Blockchain.caller();
230
229
 
231
230
  if (onlyOwner) this.onlyOwner(callee);
232
-
233
231
  if (caller !== callee) throw new Revert(`callee != caller`);
234
- if (callee !== this.owner) throw new Revert('Only indexers can mint tokens');
235
232
 
236
233
  if (!this.balanceOfMap.has(to)) {
237
234
  this.balanceOfMap.set(to, value);
@@ -271,14 +268,10 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
271
268
  const newBalance: u256 = SafeMath.sub(balance, value);
272
269
  this.balanceOfMap.set(caller, newBalance);
273
270
 
274
- if (!this.balanceOfMap.has(to)) {
275
- this.balanceOfMap.set(to, value);
276
- } else {
277
- const toBalance: u256 = this.balanceOfMap.get(to);
278
- const newToBalance: u256 = SafeMath.add(toBalance, value);
271
+ const toBalance: u256 = this.balanceOfMap.get(to);
272
+ const newToBalance: u256 = SafeMath.add(toBalance, value);
279
273
 
280
- this.balanceOfMap.set(to, newToBalance);
281
- }
274
+ this.balanceOfMap.set(to, newToBalance);
282
275
 
283
276
  this.createTransferEvent(caller, to, value);
284
277
 
@@ -345,19 +338,19 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
345
338
  this.emitEvent(burnEvent);
346
339
  }
347
340
 
348
- private createApproveEvent(owner: Address, spender: Address, value: u256): void {
341
+ protected createApproveEvent(owner: Address, spender: Address, value: u256): void {
349
342
  const approveEvent = new ApproveEvent(owner, spender, value);
350
343
 
351
344
  this.emitEvent(approveEvent);
352
345
  }
353
346
 
354
- private createMintEvent(owner: Address, value: u256): void {
347
+ protected createMintEvent(owner: Address, value: u256): void {
355
348
  const mintEvent = new MintEvent(owner, value);
356
349
 
357
350
  this.emitEvent(mintEvent);
358
351
  }
359
352
 
360
- private createTransferEvent(from: Address, to: Address, value: u256): void {
353
+ protected createTransferEvent(from: Address, to: Address, value: u256): void {
361
354
  const transferEvent = new TransferEvent(from, to, value);
362
355
 
363
356
  this.emitEvent(transferEvent);
@@ -3,10 +3,6 @@ import { Calldata } from '../../universal/ABIRegistry';
3
3
  import { StoredU256 } from '../../storage/StoredU256';
4
4
 
5
5
  export interface IOP_20 {
6
- readonly name: string;
7
- readonly symbol: string;
8
-
9
- readonly decimals: u8;
10
6
  readonly _totalSupply: StoredU256;
11
7
 
12
8
  balanceOf(callData: Calldata): BytesWriter;
@@ -11,7 +11,7 @@ import { Potential } from '../lang/Definitions';
11
11
  import { Map } from '../generic/Map';
12
12
  import { OP_NET } from '../contracts/OP_NET';
13
13
  import { PointerStorage } from '../types';
14
- import { deploy, deployFromAddress, loadPointer, storePointer } from './global';
14
+ import { callContract, deploy, deployFromAddress, loadPointer, log, storePointer } from './global';
15
15
  import { DeployContractResponse } from '../interfaces/DeployContractResponse';
16
16
 
17
17
  export * from '../env/global';
@@ -81,6 +81,10 @@ export class BlockchainEnvironment {
81
81
  return this.currentBlock;
82
82
  }
83
83
 
84
+ public get blockNumberU64(): u64 {
85
+ return this.currentBlock.toU64();
86
+ }
87
+
84
88
  public callee(): Address {
85
89
  if (!this._callee) {
86
90
  throw this.error('Callee is required');
@@ -111,25 +115,25 @@ export class BlockchainEnvironment {
111
115
  }
112
116
 
113
117
  public call(destinationContract: Address, calldata: BytesWriter): BytesReader {
114
- /*if (destinationContract === this._callee) {
118
+ if (destinationContract === this._callee) {
115
119
  throw this.error('Cannot call self');
116
120
  }
117
121
 
118
- const externalCalls = this.externalCalls.get(destinationContract);
119
- const buffer = calldata.getBuffer();
120
- externalCalls.push(buffer);
122
+ const call = new BytesWriter();
123
+ call.writeAddress(destinationContract);
124
+ call.writeBytesWithLength(calldata.getBuffer());
121
125
 
122
- const response: Potential<Uint8Array> = this.getExternalCallResponse(
123
- destinationContract,
124
- externalCalls.length - 1,
125
- );
126
- if (!response) {
127
- throw this.error('external call failed');
128
- }
126
+ const response: Uint8Array = callContract(call.getBuffer());
129
127
 
130
- return new BytesReader(response);*/
128
+ return new BytesReader(response);
129
+ }
131
130
 
132
- throw this.error('Not implemented');
131
+ public log(data: string): void {
132
+ const writer = new BytesWriter();
133
+ writer.writeStringWithLength(data);
134
+
135
+ const buffer = writer.getBuffer();
136
+ log(buffer);
133
137
  }
134
138
 
135
139
  public addEvent(event: NetEvent): void {
@@ -221,10 +225,8 @@ export class BlockchainEnvironment {
221
225
  pointer: u16,
222
226
  keyPointer: MemorySlotPointer,
223
227
  value: MemorySlotData<u256>,
224
- defaultValue: MemorySlotData<u256>,
225
228
  ): void {
226
229
  const pointerHash: u256 = encodePointerHash(pointer, keyPointer);
227
- this.ensureStorageAtPointer(pointerHash, defaultValue);
228
230
 
229
231
  this._internalSetStorageAt(pointerHash, value);
230
232
  }
@@ -241,11 +243,6 @@ export class BlockchainEnvironment {
241
243
  return ABIRegistry.getWriteMethods();
242
244
  }
243
245
 
244
- private purgeMemory(): void {
245
- this.storage.clear();
246
- this.events = [];
247
- }
248
-
249
246
  private error(msg: string): Error {
250
247
  return new Error(`${BlockchainEnvironment.runtimeException}: ${msg}`);
251
248
  }
@@ -264,10 +261,6 @@ export class BlockchainEnvironment {
264
261
 
265
262
  this.storage.set(pointerHash, value);
266
263
 
267
- if (u256.eq(value, u256.Zero)) {
268
- return;
269
- }
270
-
271
264
  const writer: BytesWriter = new BytesWriter();
272
265
  writer.writeU256(pointerHash);
273
266
  writer.writeU256(value);
@@ -305,6 +298,10 @@ export class BlockchainEnvironment {
305
298
  defaultValue: MemorySlotData<u256>,
306
299
  ): void {
307
300
  if (!this.hasPointerStorageHash(pointerHash)) {
301
+ if (u256.eq(defaultValue, u256.Zero)) {
302
+ return;
303
+ }
304
+
308
305
  this._internalSetStorageAt(pointerHash, defaultValue);
309
306
  }
310
307
  }
@@ -17,3 +17,7 @@ export declare function deployFromAddress(data: Uint8Array): Uint8Array;
17
17
  // @ts-ignore
18
18
  @external('env', 'call')
19
19
  export declare function callContract(data: Uint8Array): Uint8Array;
20
+
21
+ // @ts-ignore
22
+ @external('env', 'log')
23
+ export declare function log(data: Uint8Array): void;
package/runtime/index.ts CHANGED
@@ -43,6 +43,7 @@ export * from './memory/MultiAddressMemoryMap';
43
43
 
44
44
  /** Storage */
45
45
  export * from './storage/StoredU256';
46
+ export * from './storage/StoredString';
46
47
 
47
48
  /** Universal */
48
49
  export * from './universal/ABIRegistry';
@@ -17,7 +17,7 @@ export class AddressMemoryMap<K extends string, V extends MemorySlotData<u256>>
17
17
 
18
18
  public set(key: K, value: V): this {
19
19
  const keyHash: MemorySlotPointer = encodePointer(key);
20
- Blockchain.setStorageAt(this.pointer, keyHash, value, this.defaultValue);
20
+ Blockchain.setStorageAt(this.pointer, keyHash, value);
21
21
 
22
22
  return this;
23
23
  }
@@ -24,7 +24,7 @@ export class KeyMerger<K extends string, K2 extends string, V extends MemorySlot
24
24
  const mergedKey: string = `${this.parentKey}${key2}`;
25
25
  const keyHash: MemorySlotPointer = encodePointer(mergedKey);
26
26
 
27
- Blockchain.setStorageAt(this.pointer, keyHash, value, this.defaultValue);
27
+ Blockchain.setStorageAt(this.pointer, keyHash, value);
28
28
 
29
29
  return this;
30
30
  }
@@ -0,0 +1,145 @@
1
+ import { u256 } from 'as-bignum/assembly';
2
+ import { Blockchain } from '../env';
3
+ import { SafeMath } from '../types/SafeMath';
4
+
5
+ @final
6
+ export class StoredString {
7
+ constructor(
8
+ public pointer: u16,
9
+ private defaultValue?: string,
10
+ ) {}
11
+
12
+ private _value: string = '';
13
+
14
+ @inline
15
+ public get value(): string {
16
+ if (!this._value) {
17
+ this.load();
18
+ }
19
+
20
+ return this._value;
21
+ }
22
+
23
+ @inline
24
+ public set value(value: string) {
25
+ this._value = value;
26
+ this.save();
27
+ }
28
+
29
+ private min(a: u32, b: u32): u32 {
30
+ return a < b ? a : b;
31
+ }
32
+
33
+ private max(a: u32, b: u32): u32 {
34
+ return a > b ? a : b;
35
+ }
36
+
37
+ private save(): void {
38
+ const length: u32 = this._value.length;
39
+ if (length == 0) {
40
+ return;
41
+ }
42
+
43
+ if (length > 2048) {
44
+ throw new Error('StoredString: value is too long');
45
+ }
46
+
47
+ // Prepare the header with the length of the string in the first 4 bytes
48
+ let header: u256 = u256.fromU32(length);
49
+ header = SafeMath.shl(header, 224);
50
+
51
+ let currentPointer: u256 = u256.Zero;
52
+ let remainingLength: u32 = length;
53
+ let offset: u32 = 0;
54
+
55
+ // Save the initial chunk (first 28 bytes) in the header
56
+ let bytesToWrite: u32 = this.min(remainingLength, 28);
57
+ header = this.saveChunk(header, this._value, offset, bytesToWrite, 4);
58
+ Blockchain.setStorageAt(this.pointer, currentPointer, header);
59
+
60
+ remainingLength -= bytesToWrite;
61
+ offset += bytesToWrite;
62
+
63
+ // Save the remaining chunks in subsequent storage slots
64
+ while (remainingLength > 0) {
65
+ bytesToWrite = this.min(remainingLength, 32);
66
+ let storageValue: u256 = this.saveChunk(
67
+ u256.Zero,
68
+ this._value,
69
+ offset,
70
+ bytesToWrite,
71
+ 0,
72
+ );
73
+ currentPointer = u256.add(currentPointer, u256.One);
74
+ Blockchain.setStorageAt(this.pointer, currentPointer, storageValue);
75
+
76
+ remainingLength -= bytesToWrite;
77
+ offset += bytesToWrite;
78
+ }
79
+ }
80
+
81
+ // Helper method to save a chunk of the string into the storage slot
82
+ private saveChunk(
83
+ storage: u256,
84
+ value: string,
85
+ offset: u32,
86
+ length: u32,
87
+ storageOffset: u32,
88
+ ): u256 {
89
+ let bytes = storage.toBytes(true);
90
+ for (let i: u32 = 0; i < length; i++) {
91
+ let index: i32 = i32(offset + i);
92
+ bytes[i + storageOffset] = u8(value.charCodeAt(index));
93
+ }
94
+ return u256.fromBytes(bytes, true);
95
+ }
96
+
97
+ private load(): void {
98
+ const header: u256 = Blockchain.getStorageAt(this.pointer, u256.Zero, u256.Zero);
99
+ if (u256.eq(header, u256.Zero)) {
100
+ if (this.defaultValue) {
101
+ this.value = this.defaultValue;
102
+ }
103
+
104
+ return;
105
+ }
106
+
107
+ // the length of the string is stored in the first 4 bytes of the header
108
+ const bits: u256 = u256.shr(header, 224);
109
+ const length: u32 = bits.toU32();
110
+
111
+ // the rest contains the string itself
112
+ let currentPointer: u256 = u256.Zero;
113
+ let remainingLength: u32 = length;
114
+ let currentStorage: u256 = header;
115
+
116
+ let bytesToRead: u32 = this.min(remainingLength, 28);
117
+ let str: string = this.loadChunk(currentStorage, 4, bytesToRead);
118
+ remainingLength -= bytesToRead;
119
+
120
+ while (remainingLength > 0) {
121
+ // Move to the next storage slot
122
+ currentPointer = u256.add(currentPointer, u256.One);
123
+ currentStorage = Blockchain.getStorageAt(this.pointer, currentPointer, u256.Zero);
124
+
125
+ // Extract the relevant portion of the string from the current storage slot
126
+ let bytesToRead: u32 = this.min(remainingLength, 32);
127
+ str += this.loadChunk(currentStorage, 0, bytesToRead);
128
+
129
+ remainingLength -= bytesToRead;
130
+ }
131
+
132
+ this._value = str;
133
+ }
134
+
135
+ private loadChunk(value: u256, offset: u32, length: u32): string {
136
+ const bytes = value.toBytes(true);
137
+
138
+ let str: string = '';
139
+ for (let i: u32 = 0; i < length; i++) {
140
+ str += String.fromCharCode(bytes[i + offset]);
141
+ }
142
+
143
+ return str;
144
+ }
145
+ }
@@ -9,9 +9,7 @@ export class StoredU256 {
9
9
  public pointer: u16,
10
10
  public subPointer: MemorySlotPointer,
11
11
  private defaultValue: u256,
12
- ) {
13
- this._value = Blockchain.getStorageAt(this.pointer, this.subPointer, this.defaultValue);
14
- }
12
+ ) {}
15
13
 
16
14
  private _value: u256 = u256.Zero;
17
15
 
@@ -26,7 +24,7 @@ export class StoredU256 {
26
24
  public set value(value: u256) {
27
25
  this._value = value;
28
26
 
29
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
27
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
30
28
  }
31
29
 
32
30
  @inline
@@ -40,7 +38,7 @@ export class StoredU256 {
40
38
  this.ensureValue();
41
39
 
42
40
  this._value = SafeMath.add(this._value, value);
43
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
41
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
44
42
 
45
43
  return this;
46
44
  }
@@ -51,7 +49,7 @@ export class StoredU256 {
51
49
  this.ensureValue();
52
50
 
53
51
  this._value = SafeMath.sub(this._value, value);
54
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
52
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
55
53
 
56
54
  return this;
57
55
  }
@@ -62,7 +60,7 @@ export class StoredU256 {
62
60
  this.ensureValue();
63
61
 
64
62
  this._value = SafeMath.mul(this._value, value);
65
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
63
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
66
64
 
67
65
  return this;
68
66
  }
@@ -121,7 +119,7 @@ export class StoredU256 {
121
119
  this.ensureValue();
122
120
 
123
121
  this._value = u256.shr(this._value, value);
124
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
122
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
125
123
 
126
124
  return this;
127
125
  }
@@ -132,7 +130,7 @@ export class StoredU256 {
132
130
  this.ensureValue();
133
131
 
134
132
  this._value = u256.and(this._value, value);
135
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
133
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
136
134
 
137
135
  return this;
138
136
  }
@@ -143,7 +141,7 @@ export class StoredU256 {
143
141
  this.ensureValue();
144
142
 
145
143
  this._value = u256.or(this._value, value);
146
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
144
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
147
145
 
148
146
  return this;
149
147
  }
@@ -154,7 +152,7 @@ export class StoredU256 {
154
152
  this.ensureValue();
155
153
 
156
154
  this._value = u256.xor(this._value, value);
157
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
155
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
158
156
 
159
157
  return this;
160
158
  }
@@ -176,7 +174,7 @@ export class StoredU256 {
176
174
  value = u256.shr(value, 1);
177
175
  }
178
176
 
179
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
177
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
180
178
 
181
179
  return this;
182
180
  }
@@ -201,7 +199,7 @@ export class StoredU256 {
201
199
  }
202
200
 
203
201
  this._value = result;
204
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
202
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
205
203
 
206
204
  return this;
207
205
  }
@@ -212,7 +210,7 @@ export class StoredU256 {
212
210
  this.ensureValue();
213
211
 
214
212
  this._value = SafeMath.add(this._value, u256.One);
215
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
213
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
216
214
 
217
215
  return this;
218
216
  }
@@ -223,7 +221,7 @@ export class StoredU256 {
223
221
  this.ensureValue();
224
222
 
225
223
  this._value = SafeMath.sub(this._value, u256.One);
226
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
224
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
227
225
 
228
226
  return this;
229
227
  }
@@ -232,7 +230,7 @@ export class StoredU256 {
232
230
  public set(value: u256): this {
233
231
  this._value = value;
234
232
 
235
- Blockchain.setStorageAt(this.pointer, this.subPointer, this._value, this.defaultValue);
233
+ Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
236
234
 
237
235
  return this;
238
236
  }
@@ -1,5 +1,5 @@
1
1
  import { Potential } from '../lang/Definitions';
2
2
 
3
- export const ADDRESS_BYTE_LENGTH: u8 = 64;
3
+ export const ADDRESS_BYTE_LENGTH: u8 = 66;
4
4
  export declare type Address = string;
5
5
  export declare type PotentialAddress = Potential<Address>;
@@ -19,6 +19,30 @@ export class SafeMath {
19
19
  return u256.sub(a, b);
20
20
  }
21
21
 
22
+ // Computes (a * b) % modulus with full precision
23
+ public static mulmod(a: u256, b: u256, modulus: u256): u256 {
24
+ if (u256.eq(modulus, u256.Zero)) throw new Error('SafeMath: modulo by zero');
25
+
26
+ const mul = SafeMath.mul(a, b);
27
+ return SafeMath.mod(mul, modulus);
28
+ }
29
+
30
+ @inline
31
+ @unsafe
32
+ @operator('%')
33
+ public static mod(a: u256, b: u256): u256 {
34
+ if (u256.eq(b, u256.Zero)) {
35
+ throw new Error('SafeMath: modulo by zero');
36
+ }
37
+
38
+ let result = a.clone();
39
+ while (u256.ge(result, b)) {
40
+ result = u256.sub(result, b);
41
+ }
42
+
43
+ return result;
44
+ }
45
+
22
46
  public static mul(a: u256, b: u256): u256 {
23
47
  if (a === SafeMath.ZERO || b === SafeMath.ZERO) {
24
48
  return SafeMath.ZERO;
@@ -37,7 +61,7 @@ export class SafeMath {
37
61
  @inline
38
62
  @unsafe
39
63
  @operator('/')
40
- static div(a: u256, b: u256): u256 {
64
+ public static div(a: u256, b: u256): u256 {
41
65
  if (b.isZero()) {
42
66
  throw new Error('Division by zero');
43
67
  }
@@ -64,7 +88,7 @@ export class SafeMath {
64
88
  for (let i = shift; i >= 0; i--) {
65
89
  if (u256.ge(n, d)) {
66
90
  n = u256.sub(n, d);
67
- result = u256.or(result, SafeMath.shl(new u256(1), i));
91
+ result = u256.or(result, SafeMath.shl(u256.One, i));
68
92
  }
69
93
  d = u256.shr(d, 1); // restore d to original by shifting right
70
94
  }
@@ -86,16 +110,23 @@ export class SafeMath {
86
110
  if (u256.gt(y, u256.fromU32(3))) {
87
111
  let z = y;
88
112
 
89
- let x = SafeMath.add(SafeMath.div(y, u256.fromU32(2)), u256.fromU32(1));
113
+ let u246_2 = u256.fromU32(2);
114
+
115
+ let d = SafeMath.div(y, u246_2);
116
+ let x = SafeMath.add(d, u256.One);
117
+
90
118
  while (u256.lt(x, z)) {
91
119
  z = x;
92
120
 
93
121
  let u = SafeMath.div(y, x);
94
- x = SafeMath.div(u256.add(u, x), u256.fromU32(2));
122
+ let y2 = u256.add(u, x);
123
+
124
+ x = SafeMath.div(y2, u246_2);
95
125
  }
126
+
96
127
  return z;
97
128
  } else if (!u256.eq(y, u256.Zero)) {
98
- return u256.fromU32(1);
129
+ return u256.One;
99
130
  } else {
100
131
  return u256.Zero;
101
132
  }
@@ -103,7 +134,7 @@ export class SafeMath {
103
134
 
104
135
  @inline
105
136
  @unsafe
106
- static shl(value: u256, shift: i32): u256 {
137
+ public static shl(value: u256, shift: i32): u256 {
107
138
  if (shift == 0) {
108
139
  return value.clone();
109
140
  }