@btc-vision/btc-runtime 1.0.11 → 1.0.13
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 +2 -2
- package/package.json +1 -1
- package/runtime/contracts/OP_20.ts +16 -23
- package/runtime/contracts/interfaces/IOP_20.ts +0 -4
- package/runtime/env/BTCEnvironment.ts +18 -25
- package/runtime/env/global.ts +4 -0
- package/runtime/memory/AddressMemoryMap.ts +1 -1
- package/runtime/memory/KeyMerger.ts +1 -1
- package/runtime/storage/StoredString.ts +145 -0
- package/runtime/storage/StoredU256.ts +14 -16
- package/runtime/types/SafeMath.ts +11 -4
package/README.md
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
## Introduction
|
|
13
13
|
|
|
14
|
-
The OPNet Smart Contract Runtime
|
|
15
|
-
The runtime is written in AssemblyScript
|
|
14
|
+
The OPNet Smart Contract Runtime contains all the necessary components to effectively create smart contracts for Bitcoin
|
|
15
|
+
L1. The runtime is written in AssemblyScript.
|
|
16
16
|
|
|
17
17
|
### Installation
|
|
18
18
|
|
package/package.json
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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.
|
|
158
|
+
response.writeStringWithLength(this.name);
|
|
160
159
|
break;
|
|
161
160
|
case encodeSelector('symbol'):
|
|
162
|
-
response.
|
|
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
|
-
|
|
275
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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';
|
|
@@ -111,25 +111,25 @@ export class BlockchainEnvironment {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
public call(destinationContract: Address, calldata: BytesWriter): BytesReader {
|
|
114
|
-
|
|
114
|
+
if (destinationContract === this._callee) {
|
|
115
115
|
throw this.error('Cannot call self');
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
const call = new BytesWriter();
|
|
119
|
+
call.writeAddress(destinationContract);
|
|
120
|
+
call.writeBytesWithLength(calldata.getBuffer());
|
|
121
121
|
|
|
122
|
-
const response:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (!response) {
|
|
127
|
-
throw this.error('external call failed');
|
|
128
|
-
}
|
|
122
|
+
const response: Uint8Array = callContract(call.getBuffer());
|
|
123
|
+
|
|
124
|
+
return new BytesReader(response);
|
|
125
|
+
}
|
|
129
126
|
|
|
130
|
-
|
|
127
|
+
public log(data: string): void {
|
|
128
|
+
const writer = new BytesWriter();
|
|
129
|
+
writer.writeStringWithLength(data);
|
|
131
130
|
|
|
132
|
-
|
|
131
|
+
const buffer = writer.getBuffer();
|
|
132
|
+
log(buffer);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
public addEvent(event: NetEvent): void {
|
|
@@ -221,10 +221,8 @@ export class BlockchainEnvironment {
|
|
|
221
221
|
pointer: u16,
|
|
222
222
|
keyPointer: MemorySlotPointer,
|
|
223
223
|
value: MemorySlotData<u256>,
|
|
224
|
-
defaultValue: MemorySlotData<u256>,
|
|
225
224
|
): void {
|
|
226
225
|
const pointerHash: u256 = encodePointerHash(pointer, keyPointer);
|
|
227
|
-
this.ensureStorageAtPointer(pointerHash, defaultValue);
|
|
228
226
|
|
|
229
227
|
this._internalSetStorageAt(pointerHash, value);
|
|
230
228
|
}
|
|
@@ -241,11 +239,6 @@ export class BlockchainEnvironment {
|
|
|
241
239
|
return ABIRegistry.getWriteMethods();
|
|
242
240
|
}
|
|
243
241
|
|
|
244
|
-
private purgeMemory(): void {
|
|
245
|
-
this.storage.clear();
|
|
246
|
-
this.events = [];
|
|
247
|
-
}
|
|
248
|
-
|
|
249
242
|
private error(msg: string): Error {
|
|
250
243
|
return new Error(`${BlockchainEnvironment.runtimeException}: ${msg}`);
|
|
251
244
|
}
|
|
@@ -264,10 +257,6 @@ export class BlockchainEnvironment {
|
|
|
264
257
|
|
|
265
258
|
this.storage.set(pointerHash, value);
|
|
266
259
|
|
|
267
|
-
if (u256.eq(value, u256.Zero)) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
260
|
const writer: BytesWriter = new BytesWriter();
|
|
272
261
|
writer.writeU256(pointerHash);
|
|
273
262
|
writer.writeU256(value);
|
|
@@ -305,6 +294,10 @@ export class BlockchainEnvironment {
|
|
|
305
294
|
defaultValue: MemorySlotData<u256>,
|
|
306
295
|
): void {
|
|
307
296
|
if (!this.hasPointerStorageHash(pointerHash)) {
|
|
297
|
+
if (u256.eq(defaultValue, u256.Zero)) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
308
301
|
this._internalSetStorageAt(pointerHash, defaultValue);
|
|
309
302
|
}
|
|
310
303
|
}
|
package/runtime/env/global.ts
CHANGED
|
@@ -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;
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
233
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
236
234
|
|
|
237
235
|
return this;
|
|
238
236
|
}
|
|
@@ -64,7 +64,7 @@ export class SafeMath {
|
|
|
64
64
|
for (let i = shift; i >= 0; i--) {
|
|
65
65
|
if (u256.ge(n, d)) {
|
|
66
66
|
n = u256.sub(n, d);
|
|
67
|
-
result = u256.or(result, SafeMath.shl(
|
|
67
|
+
result = u256.or(result, SafeMath.shl(u256.One, i));
|
|
68
68
|
}
|
|
69
69
|
d = u256.shr(d, 1); // restore d to original by shifting right
|
|
70
70
|
}
|
|
@@ -86,16 +86,23 @@ export class SafeMath {
|
|
|
86
86
|
if (u256.gt(y, u256.fromU32(3))) {
|
|
87
87
|
let z = y;
|
|
88
88
|
|
|
89
|
-
let
|
|
89
|
+
let u246_2 = u256.fromU32(2);
|
|
90
|
+
|
|
91
|
+
let d = SafeMath.div(y, u246_2);
|
|
92
|
+
let x = SafeMath.add(d, u256.One);
|
|
93
|
+
|
|
90
94
|
while (u256.lt(x, z)) {
|
|
91
95
|
z = x;
|
|
92
96
|
|
|
93
97
|
let u = SafeMath.div(y, x);
|
|
94
|
-
|
|
98
|
+
let y2 = u256.add(u, x);
|
|
99
|
+
|
|
100
|
+
x = SafeMath.div(y2, u246_2);
|
|
95
101
|
}
|
|
102
|
+
|
|
96
103
|
return z;
|
|
97
104
|
} else if (!u256.eq(y, u256.Zero)) {
|
|
98
|
-
return u256.
|
|
105
|
+
return u256.One;
|
|
99
106
|
} else {
|
|
100
107
|
return u256.Zero;
|
|
101
108
|
}
|