@btc-vision/btc-runtime 1.0.10 → 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 -35
- package/runtime/contracts/interfaces/IOP_20.ts +0 -4
- package/runtime/env/BTCEnvironment.ts +58 -157
- package/runtime/env/global.ts +7 -5
- package/runtime/exports/index.ts +0 -20
- package/runtime/index.ts +3 -0
- package/runtime/interfaces/DeployContractResponse.ts +12 -0
- package/runtime/memory/AddressMemoryMap.ts +3 -23
- package/runtime/memory/KeyMerger.ts +3 -22
- package/runtime/memory/MultiAddressMemoryMap.ts +1 -14
- package/runtime/storage/StoredString.ts +145 -0
- package/runtime/storage/StoredU256.ts +15 -107
- 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,41 +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
|
-
Blockchain.contractAddress,
|
|
40
39
|
u256.Zero,
|
|
41
40
|
);
|
|
41
|
+
|
|
42
42
|
this.balanceOfMap = new AddressMemoryMap<Address, MemorySlotData<u256>>(
|
|
43
43
|
Blockchain.nextPointer,
|
|
44
|
-
Blockchain.contractAddress,
|
|
45
44
|
u256.Zero,
|
|
46
45
|
);
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
const supply: u256 = Blockchain.getStorageAt(
|
|
50
|
-
Blockchain.contractAddress,
|
|
51
|
-
supplyPointer,
|
|
52
|
-
u256.Zero,
|
|
53
|
-
u256.Zero,
|
|
54
|
-
);
|
|
55
|
-
this._totalSupply = new StoredU256(
|
|
56
|
-
Blockchain.contractAddress,
|
|
57
|
-
supplyPointer,
|
|
58
|
-
u256.Zero,
|
|
59
|
-
supply,
|
|
60
|
-
);
|
|
47
|
+
this._totalSupply = new StoredU256(Blockchain.nextPointer, u256.Zero, u256.Zero);
|
|
61
48
|
}
|
|
62
49
|
|
|
63
50
|
public _totalSupply: StoredU256;
|
|
@@ -168,10 +155,10 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
|
|
|
168
155
|
response.writeU8(this.decimals);
|
|
169
156
|
break;
|
|
170
157
|
case encodeSelector('name'):
|
|
171
|
-
response.
|
|
158
|
+
response.writeStringWithLength(this.name);
|
|
172
159
|
break;
|
|
173
160
|
case encodeSelector('symbol'):
|
|
174
|
-
response.
|
|
161
|
+
response.writeStringWithLength(this.symbol);
|
|
175
162
|
break;
|
|
176
163
|
case encodeSelector('totalSupply'):
|
|
177
164
|
response.writeU256(this.totalSupply);
|
|
@@ -241,9 +228,7 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
|
|
|
241
228
|
const caller = Blockchain.caller();
|
|
242
229
|
|
|
243
230
|
if (onlyOwner) this.onlyOwner(callee);
|
|
244
|
-
|
|
245
231
|
if (caller !== callee) throw new Revert(`callee != caller`);
|
|
246
|
-
if (callee !== this.owner) throw new Revert('Only indexers can mint tokens');
|
|
247
232
|
|
|
248
233
|
if (!this.balanceOfMap.has(to)) {
|
|
249
234
|
this.balanceOfMap.set(to, value);
|
|
@@ -283,14 +268,10 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
|
|
|
283
268
|
const newBalance: u256 = SafeMath.sub(balance, value);
|
|
284
269
|
this.balanceOfMap.set(caller, newBalance);
|
|
285
270
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
} else {
|
|
289
|
-
const toBalance: u256 = this.balanceOfMap.get(to);
|
|
290
|
-
const newToBalance: u256 = SafeMath.add(toBalance, value);
|
|
271
|
+
const toBalance: u256 = this.balanceOfMap.get(to);
|
|
272
|
+
const newToBalance: u256 = SafeMath.add(toBalance, value);
|
|
291
273
|
|
|
292
|
-
|
|
293
|
-
}
|
|
274
|
+
this.balanceOfMap.set(to, newToBalance);
|
|
294
275
|
|
|
295
276
|
this.createTransferEvent(caller, to, value);
|
|
296
277
|
|
|
@@ -357,19 +338,19 @@ export abstract class OP_20 extends OP_NET implements IOP_20 {
|
|
|
357
338
|
this.emitEvent(burnEvent);
|
|
358
339
|
}
|
|
359
340
|
|
|
360
|
-
|
|
341
|
+
protected createApproveEvent(owner: Address, spender: Address, value: u256): void {
|
|
361
342
|
const approveEvent = new ApproveEvent(owner, spender, value);
|
|
362
343
|
|
|
363
344
|
this.emitEvent(approveEvent);
|
|
364
345
|
}
|
|
365
346
|
|
|
366
|
-
|
|
347
|
+
protected createMintEvent(owner: Address, value: u256): void {
|
|
367
348
|
const mintEvent = new MintEvent(owner, value);
|
|
368
349
|
|
|
369
350
|
this.emitEvent(mintEvent);
|
|
370
351
|
}
|
|
371
352
|
|
|
372
|
-
|
|
353
|
+
protected createTransferEvent(from: Address, to: Address, value: u256): void {
|
|
373
354
|
const transferEvent = new TransferEvent(from, to, value);
|
|
374
355
|
|
|
375
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;
|
|
@@ -10,8 +10,9 @@ import { MAX_EVENTS, NetEvent } from '../events/NetEvent';
|
|
|
10
10
|
import { Potential } from '../lang/Definitions';
|
|
11
11
|
import { Map } from '../generic/Map';
|
|
12
12
|
import { OP_NET } from '../contracts/OP_NET';
|
|
13
|
-
import {
|
|
14
|
-
import { deploy, deployFromAddress } from './global';
|
|
13
|
+
import { PointerStorage } from '../types';
|
|
14
|
+
import { callContract, deploy, deployFromAddress, loadPointer, log, storePointer } from './global';
|
|
15
|
+
import { DeployContractResponse } from '../interfaces/DeployContractResponse';
|
|
15
16
|
|
|
16
17
|
export * from '../env/global';
|
|
17
18
|
|
|
@@ -19,12 +20,7 @@ export * from '../env/global';
|
|
|
19
20
|
export class BlockchainEnvironment {
|
|
20
21
|
private static readonly runtimeException: string = 'RuntimeException';
|
|
21
22
|
|
|
22
|
-
private storage:
|
|
23
|
-
private initializedStorage: BlockchainStorage = new Map();
|
|
24
|
-
|
|
25
|
-
private externalCalls: Map<Address, Uint8Array[]> = new Map();
|
|
26
|
-
private externalCallsResponse: Map<Address, Uint8Array[]> = new Map();
|
|
27
|
-
|
|
23
|
+
private storage: PointerStorage = new Map();
|
|
28
24
|
private events: NetEvent[] = [];
|
|
29
25
|
|
|
30
26
|
private _callee: PotentialAddress = null;
|
|
@@ -119,38 +115,21 @@ export class BlockchainEnvironment {
|
|
|
119
115
|
throw this.error('Cannot call self');
|
|
120
116
|
}
|
|
121
117
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const externalCalls = this.externalCalls.get(destinationContract);
|
|
127
|
-
const buffer = calldata.getBuffer();
|
|
128
|
-
externalCalls.push(buffer);
|
|
118
|
+
const call = new BytesWriter();
|
|
119
|
+
call.writeAddress(destinationContract);
|
|
120
|
+
call.writeBytesWithLength(calldata.getBuffer());
|
|
129
121
|
|
|
130
|
-
const response:
|
|
131
|
-
destinationContract,
|
|
132
|
-
externalCalls.length - 1,
|
|
133
|
-
);
|
|
134
|
-
if (!response) {
|
|
135
|
-
throw this.error('external call failed');
|
|
136
|
-
}
|
|
122
|
+
const response: Uint8Array = callContract(call.getBuffer());
|
|
137
123
|
|
|
138
124
|
return new BytesReader(response);
|
|
139
125
|
}
|
|
140
126
|
|
|
141
|
-
public
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
buffer.writeLimitedAddressBytesMap(this.externalCalls);
|
|
145
|
-
this.externalCalls.clear();
|
|
146
|
-
|
|
147
|
-
return buffer.getBuffer();
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
public loadCallsResponse(responses: Uint8Array): void {
|
|
151
|
-
const memoryReader: BytesReader = new BytesReader(responses);
|
|
127
|
+
public log(data: string): void {
|
|
128
|
+
const writer = new BytesWriter();
|
|
129
|
+
writer.writeStringWithLength(data);
|
|
152
130
|
|
|
153
|
-
|
|
131
|
+
const buffer = writer.getBuffer();
|
|
132
|
+
log(buffer);
|
|
154
133
|
}
|
|
155
134
|
|
|
156
135
|
public addEvent(event: NetEvent): void {
|
|
@@ -192,64 +171,60 @@ export class BlockchainEnvironment {
|
|
|
192
171
|
return new BytesReader(cb as Uint8Array);
|
|
193
172
|
}
|
|
194
173
|
|
|
195
|
-
public deployContractFromExisting(
|
|
174
|
+
public deployContractFromExisting(
|
|
175
|
+
existingAddress: Address,
|
|
176
|
+
salt: u256,
|
|
177
|
+
): DeployContractResponse {
|
|
196
178
|
const writer = new BytesWriter();
|
|
197
|
-
writer.writeU256(hash);
|
|
198
179
|
writer.writeAddress(existingAddress);
|
|
180
|
+
writer.writeU256(salt);
|
|
199
181
|
|
|
200
|
-
const
|
|
182
|
+
const buffer: Uint8Array = writer.getBuffer();
|
|
183
|
+
const cb: Potential<Uint8Array> = deployFromAddress(buffer);
|
|
201
184
|
if (!cb) throw this.error('Failed to deploy contract');
|
|
202
185
|
|
|
203
|
-
|
|
186
|
+
const reader: BytesReader = new BytesReader(cb as Uint8Array);
|
|
187
|
+
const virtualAddress: u256 = reader.readU256();
|
|
188
|
+
const contractAddress: Address = reader.readAddress();
|
|
189
|
+
|
|
190
|
+
return new DeployContractResponse(virtualAddress, contractAddress);
|
|
204
191
|
}
|
|
205
192
|
|
|
206
193
|
public getStorageAt(
|
|
207
|
-
address: Address,
|
|
208
194
|
pointer: u16,
|
|
209
195
|
subPointer: MemorySlotPointer,
|
|
210
196
|
defaultValue: MemorySlotData<u256>,
|
|
211
197
|
): MemorySlotData<u256> {
|
|
212
|
-
this.ensureStorageAtAddress(address);
|
|
213
|
-
|
|
214
198
|
const pointerHash: MemorySlotPointer = encodePointerHash(pointer, subPointer);
|
|
215
|
-
this.ensureStorageAtPointer(
|
|
216
|
-
|
|
217
|
-
const storage: PointerStorage = this.storage.get(address);
|
|
199
|
+
this.ensureStorageAtPointer(pointerHash, defaultValue);
|
|
218
200
|
|
|
219
201
|
// maybe find a better way for this
|
|
220
|
-
const allKeys: u256[] = storage.keys();
|
|
202
|
+
const allKeys: u256[] = this.storage.keys();
|
|
221
203
|
for (let i: i32 = 0; i < allKeys.length; i++) {
|
|
222
204
|
const v: u256 = allKeys[i];
|
|
223
205
|
|
|
224
206
|
if (u256.eq(v, pointerHash)) {
|
|
225
|
-
return storage.get(v);
|
|
207
|
+
return this.storage.get(v);
|
|
226
208
|
}
|
|
227
209
|
}
|
|
228
210
|
|
|
229
211
|
return defaultValue;
|
|
230
212
|
}
|
|
231
213
|
|
|
232
|
-
public hasStorageAt(
|
|
233
|
-
this.ensureStorageAtAddress(address);
|
|
234
|
-
|
|
214
|
+
public hasStorageAt(pointer: u16, subPointer: MemorySlotPointer): bool {
|
|
235
215
|
// We mark zero as the default value for the storage, if something is 0, the storage slot get deleted or is non-existent
|
|
236
|
-
const val: u256 = this.getStorageAt(
|
|
216
|
+
const val: u256 = this.getStorageAt(pointer, subPointer, u256.Zero);
|
|
237
217
|
return val != u256.Zero;
|
|
238
218
|
}
|
|
239
219
|
|
|
240
220
|
public setStorageAt(
|
|
241
|
-
address: Address,
|
|
242
221
|
pointer: u16,
|
|
243
222
|
keyPointer: MemorySlotPointer,
|
|
244
223
|
value: MemorySlotData<u256>,
|
|
245
|
-
defaultValue: MemorySlotData<u256>,
|
|
246
224
|
): void {
|
|
247
|
-
this.ensureStorageAtAddress(address);
|
|
248
|
-
|
|
249
225
|
const pointerHash: u256 = encodePointerHash(pointer, keyPointer);
|
|
250
|
-
this.ensureStorageAtPointer(address, pointerHash, defaultValue);
|
|
251
226
|
|
|
252
|
-
this._internalSetStorageAt(
|
|
227
|
+
this._internalSetStorageAt(pointerHash, value);
|
|
253
228
|
}
|
|
254
229
|
|
|
255
230
|
public getViewSelectors(): Uint8Array {
|
|
@@ -264,113 +239,34 @@ export class BlockchainEnvironment {
|
|
|
264
239
|
return ABIRegistry.getWriteMethods();
|
|
265
240
|
}
|
|
266
241
|
|
|
267
|
-
public loadStorage(data: Uint8Array): void {
|
|
268
|
-
this.purgeMemory();
|
|
269
|
-
|
|
270
|
-
const memoryReader: BytesReader = new BytesReader(data);
|
|
271
|
-
const contractsSize: u32 = memoryReader.readU32();
|
|
272
|
-
|
|
273
|
-
for (let i: u32 = 0; i < contractsSize; i++) {
|
|
274
|
-
const address: Address = memoryReader.readAddress();
|
|
275
|
-
const storageSize: u32 = memoryReader.readU32();
|
|
276
|
-
|
|
277
|
-
this.ensureStorageAtAddress(address);
|
|
278
|
-
const storage: PointerStorage = this.storage.get(address);
|
|
279
|
-
|
|
280
|
-
for (let j: u32 = 0; j < storageSize; j++) {
|
|
281
|
-
const keyPointer: MemorySlotPointer = memoryReader.readU256();
|
|
282
|
-
const value: MemorySlotData<u256> = memoryReader.readU256();
|
|
283
|
-
|
|
284
|
-
storage.set(keyPointer, value);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
public storageToBytes(): Uint8Array {
|
|
290
|
-
const memoryWriter: BytesWriter = new BytesWriter();
|
|
291
|
-
memoryWriter.writeStorage(this.storage);
|
|
292
|
-
|
|
293
|
-
//this.storage.clear();
|
|
294
|
-
|
|
295
|
-
return memoryWriter.getBuffer();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
public initializedStorageToBytes(): Uint8Array {
|
|
299
|
-
const memoryWriter: BytesWriter = new BytesWriter();
|
|
300
|
-
memoryWriter.writeStorage(this.initializedStorage);
|
|
301
|
-
|
|
302
|
-
//this.initializedStorage.clear();
|
|
303
|
-
|
|
304
|
-
return memoryWriter.getBuffer();
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
private purgeMemory(): void {
|
|
308
|
-
this.storage.clear();
|
|
309
|
-
this.initializedStorage.clear();
|
|
310
|
-
|
|
311
|
-
this.events = [];
|
|
312
|
-
|
|
313
|
-
this.externalCallsResponse.clear();
|
|
314
|
-
this.externalCalls.clear();
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
private requireInitialStorage(address: Address, pointerHash: u256, defaultValue: u256): void {
|
|
318
|
-
if (!this.initializedStorage.has(address)) {
|
|
319
|
-
this.initializedStorage.set(address, new Map<u256, MemorySlotData<u256>>());
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
//load(pointerHash);
|
|
323
|
-
|
|
324
|
-
const storage = this.initializedStorage.get(address);
|
|
325
|
-
storage.set(pointerHash, defaultValue);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
private getExternalCallResponse(
|
|
329
|
-
destinationContract: Address,
|
|
330
|
-
index: i32,
|
|
331
|
-
): Potential<Uint8Array> {
|
|
332
|
-
if (!this.externalCallsResponse.has(destinationContract)) {
|
|
333
|
-
this.externalCallsResponse.set(destinationContract, []);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
const externalCallsResponse = this.externalCallsResponse.get(destinationContract);
|
|
337
|
-
return externalCallsResponse[index] || null;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
242
|
private error(msg: string): Error {
|
|
341
243
|
return new Error(`${BlockchainEnvironment.runtimeException}: ${msg}`);
|
|
342
244
|
}
|
|
343
245
|
|
|
344
|
-
private _internalSetStorageAt(
|
|
345
|
-
|
|
346
|
-
pointerHash: u256,
|
|
347
|
-
value: MemorySlotData<u256>,
|
|
348
|
-
): void {
|
|
349
|
-
const storage: PointerStorage = this.storage.get(address);
|
|
350
|
-
const keys: u256[] = storage.keys();
|
|
246
|
+
private _internalSetStorageAt(pointerHash: u256, value: MemorySlotData<u256>): void {
|
|
247
|
+
const keys: u256[] = this.storage.keys();
|
|
351
248
|
|
|
352
249
|
// Delete the old value, there is a bug with u256 and maps.
|
|
353
250
|
for (let i = 0; i < keys.length; i++) {
|
|
354
251
|
const key = keys[i];
|
|
355
252
|
|
|
356
253
|
if (u256.eq(key, pointerHash)) {
|
|
357
|
-
storage.delete(key);
|
|
254
|
+
this.storage.delete(key);
|
|
358
255
|
}
|
|
359
256
|
}
|
|
360
257
|
|
|
361
|
-
|
|
258
|
+
this.storage.set(pointerHash, value);
|
|
362
259
|
|
|
363
|
-
|
|
364
|
-
|
|
260
|
+
const writer: BytesWriter = new BytesWriter();
|
|
261
|
+
writer.writeU256(pointerHash);
|
|
262
|
+
writer.writeU256(value);
|
|
365
263
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
this.storage.set(address, new Map<u256, MemorySlotData<u256>>());
|
|
369
|
-
}
|
|
264
|
+
const buffer: Uint8Array = writer.getBuffer();
|
|
265
|
+
storePointer(buffer);
|
|
370
266
|
}
|
|
371
267
|
|
|
372
|
-
private hasPointerStorageHash(
|
|
373
|
-
const keys = storage.keys();
|
|
268
|
+
private hasPointerStorageHash(pointer: MemorySlotPointer): bool {
|
|
269
|
+
const keys = this.storage.keys();
|
|
374
270
|
|
|
375
271
|
for (let i = 0; i < keys.length; i++) {
|
|
376
272
|
const key = keys[i];
|
|
@@ -380,24 +276,29 @@ export class BlockchainEnvironment {
|
|
|
380
276
|
}
|
|
381
277
|
}
|
|
382
278
|
|
|
383
|
-
|
|
279
|
+
// we attempt to load the requested pointer.
|
|
280
|
+
const writer = new BytesWriter();
|
|
281
|
+
writer.writeU256(pointer);
|
|
282
|
+
|
|
283
|
+
const result: Uint8Array = loadPointer(writer.getBuffer());
|
|
284
|
+
const reader: BytesReader = new BytesReader(result);
|
|
285
|
+
|
|
286
|
+
const value: u256 = reader.readU256();
|
|
287
|
+
this.storage.set(pointer, value); // cache the value
|
|
288
|
+
|
|
289
|
+
return !u256.eq(value, u256.Zero);
|
|
384
290
|
}
|
|
385
291
|
|
|
386
292
|
private ensureStorageAtPointer(
|
|
387
|
-
address: Address,
|
|
388
293
|
pointerHash: MemorySlotPointer,
|
|
389
294
|
defaultValue: MemorySlotData<u256>,
|
|
390
295
|
): void {
|
|
391
|
-
if (!this.
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
// !!! -- IMPORTANT -- !!!. We have to tell the indexer that we need this storage slot to continue even if it's already defined.
|
|
396
|
-
this.requireInitialStorage(address, pointerHash, defaultValue);
|
|
296
|
+
if (!this.hasPointerStorageHash(pointerHash)) {
|
|
297
|
+
if (u256.eq(defaultValue, u256.Zero)) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
397
300
|
|
|
398
|
-
|
|
399
|
-
if (!this.hasPointerStorageHash(storage, pointerHash)) {
|
|
400
|
-
this._internalSetStorageAt(address, pointerHash, defaultValue);
|
|
301
|
+
this._internalSetStorageAt(pointerHash, defaultValue);
|
|
401
302
|
}
|
|
402
303
|
}
|
|
403
304
|
}
|
package/runtime/env/global.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { u256 } from 'as-bignum/assembly/integer/u256';
|
|
2
|
-
|
|
3
1
|
// @ts-ignore
|
|
4
2
|
@external('env', 'load')
|
|
5
|
-
export declare function
|
|
3
|
+
export declare function loadPointer(data: Uint8Array): Uint8Array;
|
|
6
4
|
|
|
7
5
|
// @ts-ignore
|
|
8
6
|
@external('env', 'store')
|
|
9
|
-
export declare function
|
|
7
|
+
export declare function storePointer(data: Uint8Array): Uint8Array;
|
|
10
8
|
|
|
11
9
|
// @ts-ignore
|
|
12
10
|
@external('env', 'deploy')
|
|
@@ -18,4 +16,8 @@ export declare function deployFromAddress(data: Uint8Array): Uint8Array;
|
|
|
18
16
|
|
|
19
17
|
// @ts-ignore
|
|
20
18
|
@external('env', 'call')
|
|
21
|
-
export declare function
|
|
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/exports/index.ts
CHANGED
|
@@ -32,26 +32,6 @@ export function getWriteMethods(): Uint8Array {
|
|
|
32
32
|
return Blockchain.getWriteMethods();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export function getModifiedStorage(): Uint8Array {
|
|
36
|
-
return Blockchain.storageToBytes();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function initializeStorage(): Uint8Array {
|
|
40
|
-
return Blockchain.initializedStorageToBytes();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function loadStorage(data: Uint8Array): void {
|
|
44
|
-
Blockchain.loadStorage(data);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function loadCallsResponse(data: Uint8Array): void {
|
|
48
|
-
Blockchain.loadCallsResponse(data);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function getCalls(): Uint8Array {
|
|
52
|
-
return Blockchain.getCalls();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
35
|
export function setEnvironment(data: Uint8Array): void {
|
|
56
36
|
Blockchain.setEnvironment(data);
|
|
57
37
|
}
|
package/runtime/index.ts
CHANGED
|
@@ -10,6 +10,9 @@ export * from './contracts/OP_NET';
|
|
|
10
10
|
export * from './buffer/BytesReader';
|
|
11
11
|
export * from './buffer/BytesWriter';
|
|
12
12
|
|
|
13
|
+
/** Interfaces */
|
|
14
|
+
export * from './interfaces/DeployContractResponse';
|
|
15
|
+
|
|
13
16
|
/** Events */
|
|
14
17
|
export * from './events/NetEvent';
|
|
15
18
|
export * from './events/predefined';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { u256 } from 'as-bignum/assembly';
|
|
2
|
+
import { Address } from '../types/Address';
|
|
3
|
+
|
|
4
|
+
export class DeployContractResponse {
|
|
5
|
+
readonly virtualAddress: u256;
|
|
6
|
+
readonly contractAddress: Address;
|
|
7
|
+
|
|
8
|
+
constructor(virtualAddress: u256, contractAddress: Address) {
|
|
9
|
+
this.virtualAddress = virtualAddress;
|
|
10
|
+
this.contractAddress = contractAddress;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MemorySlotPointer } from './MemorySlotPointer';
|
|
2
2
|
import { Blockchain } from '../env';
|
|
3
|
-
import { Address } from '../types/Address';
|
|
4
3
|
import { encodePointer } from '../math/abi';
|
|
5
4
|
import { MemorySlotData } from './MemorySlot';
|
|
6
5
|
import { u256 } from 'as-bignum/assembly';
|
|
@@ -9,45 +8,26 @@ import { u256 } from 'as-bignum/assembly';
|
|
|
9
8
|
export class AddressMemoryMap<K extends string, V extends MemorySlotData<u256>> {
|
|
10
9
|
public pointer: u16;
|
|
11
10
|
|
|
12
|
-
private readonly memoryAllocatorAddress: Address;
|
|
13
|
-
|
|
14
11
|
constructor(
|
|
15
12
|
pointer: u16,
|
|
16
|
-
self: Address,
|
|
17
13
|
private readonly defaultValue: V,
|
|
18
14
|
) {
|
|
19
15
|
this.pointer = pointer;
|
|
20
|
-
this.memoryAllocatorAddress = self;
|
|
21
16
|
}
|
|
22
17
|
|
|
23
18
|
public set(key: K, value: V): this {
|
|
24
19
|
const keyHash: MemorySlotPointer = encodePointer(key);
|
|
25
|
-
Blockchain.setStorageAt(
|
|
26
|
-
this.memoryAllocatorAddress,
|
|
27
|
-
this.pointer,
|
|
28
|
-
keyHash,
|
|
29
|
-
value,
|
|
30
|
-
this.defaultValue,
|
|
31
|
-
);
|
|
20
|
+
Blockchain.setStorageAt(this.pointer, keyHash, value);
|
|
32
21
|
|
|
33
22
|
return this;
|
|
34
23
|
}
|
|
35
24
|
|
|
36
25
|
public get(key: K): MemorySlotData<u256> {
|
|
37
|
-
return Blockchain.getStorageAt(
|
|
38
|
-
this.memoryAllocatorAddress,
|
|
39
|
-
this.pointer,
|
|
40
|
-
encodePointer(key),
|
|
41
|
-
this.defaultValue,
|
|
42
|
-
);
|
|
26
|
+
return Blockchain.getStorageAt(this.pointer, encodePointer(key), this.defaultValue);
|
|
43
27
|
}
|
|
44
28
|
|
|
45
29
|
public has(key: K): bool {
|
|
46
|
-
return Blockchain.hasStorageAt(
|
|
47
|
-
this.memoryAllocatorAddress,
|
|
48
|
-
this.pointer,
|
|
49
|
-
encodePointer(key),
|
|
50
|
-
);
|
|
30
|
+
return Blockchain.hasStorageAt(this.pointer, encodePointer(key));
|
|
51
31
|
}
|
|
52
32
|
|
|
53
33
|
@unsafe
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { MemorySlotData } from './MemorySlot';
|
|
2
2
|
import { u256 } from 'as-bignum/assembly';
|
|
3
3
|
import { Blockchain } from '../env';
|
|
4
|
-
import { Address } from '../types/Address';
|
|
5
4
|
import { MemorySlotPointer } from './MemorySlotPointer';
|
|
6
5
|
import { encodePointer } from '../math/abi';
|
|
7
6
|
|
|
@@ -10,16 +9,13 @@ export class KeyMerger<K extends string, K2 extends string, V extends MemorySlot
|
|
|
10
9
|
public parentKey: K;
|
|
11
10
|
|
|
12
11
|
public pointer: u16;
|
|
13
|
-
private readonly memoryAllocatorAddress: Address;
|
|
14
12
|
|
|
15
13
|
constructor(
|
|
16
14
|
parent: K,
|
|
17
15
|
pointer: u16,
|
|
18
|
-
self: Address,
|
|
19
16
|
private readonly defaultValue: V,
|
|
20
17
|
) {
|
|
21
18
|
this.pointer = pointer;
|
|
22
|
-
this.memoryAllocatorAddress = self;
|
|
23
19
|
|
|
24
20
|
this.parentKey = parent;
|
|
25
21
|
}
|
|
@@ -28,13 +24,7 @@ export class KeyMerger<K extends string, K2 extends string, V extends MemorySlot
|
|
|
28
24
|
const mergedKey: string = `${this.parentKey}${key2}`;
|
|
29
25
|
const keyHash: MemorySlotPointer = encodePointer(mergedKey);
|
|
30
26
|
|
|
31
|
-
Blockchain.setStorageAt(
|
|
32
|
-
this.memoryAllocatorAddress,
|
|
33
|
-
this.pointer,
|
|
34
|
-
keyHash,
|
|
35
|
-
value,
|
|
36
|
-
this.defaultValue,
|
|
37
|
-
);
|
|
27
|
+
Blockchain.setStorageAt(this.pointer, keyHash, value);
|
|
38
28
|
|
|
39
29
|
return this;
|
|
40
30
|
}
|
|
@@ -42,22 +32,13 @@ export class KeyMerger<K extends string, K2 extends string, V extends MemorySlot
|
|
|
42
32
|
public get(key: K): MemorySlotData<u256> {
|
|
43
33
|
const mergedKey: string = `${this.parentKey}${key}`;
|
|
44
34
|
|
|
45
|
-
return Blockchain.getStorageAt(
|
|
46
|
-
this.memoryAllocatorAddress,
|
|
47
|
-
this.pointer,
|
|
48
|
-
encodePointer(mergedKey),
|
|
49
|
-
this.defaultValue,
|
|
50
|
-
);
|
|
35
|
+
return Blockchain.getStorageAt(this.pointer, encodePointer(mergedKey), this.defaultValue);
|
|
51
36
|
}
|
|
52
37
|
|
|
53
38
|
public has(key: K): bool {
|
|
54
39
|
const mergedKey: string = `${this.parentKey}${key}`;
|
|
55
40
|
|
|
56
|
-
return Blockchain.hasStorageAt(
|
|
57
|
-
this.memoryAllocatorAddress,
|
|
58
|
-
this.pointer,
|
|
59
|
-
encodePointer(mergedKey),
|
|
60
|
-
);
|
|
41
|
+
return Blockchain.hasStorageAt(this.pointer, encodePointer(mergedKey));
|
|
61
42
|
}
|
|
62
43
|
|
|
63
44
|
@unsafe
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Address } from '../types/Address';
|
|
2
1
|
import { MemorySlotData } from './MemorySlot';
|
|
3
2
|
import { u256 } from 'as-bignum/assembly';
|
|
4
3
|
import { KeyMerger } from './KeyMerger';
|
|
@@ -11,17 +10,13 @@ export class MultiAddressMemoryMap<
|
|
|
11
10
|
> extends Map<K, KeyMerger<K, K2, V>> {
|
|
12
11
|
public pointer: u16;
|
|
13
12
|
|
|
14
|
-
private readonly memoryAllocatorAddress: Address;
|
|
15
|
-
|
|
16
13
|
constructor(
|
|
17
14
|
pointer: u16,
|
|
18
|
-
self: Address,
|
|
19
15
|
private readonly defaultValue: V,
|
|
20
16
|
) {
|
|
21
17
|
super();
|
|
22
18
|
|
|
23
19
|
this.pointer = pointer;
|
|
24
|
-
this.memoryAllocatorAddress = self;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
public get(key: K): KeyMerger<K, K2, V> {
|
|
@@ -61,15 +56,7 @@ export class MultiAddressMemoryMap<
|
|
|
61
56
|
|
|
62
57
|
private createKeyMerger(key: K): void {
|
|
63
58
|
if (!super.has(key)) {
|
|
64
|
-
super.set(
|
|
65
|
-
key,
|
|
66
|
-
new KeyMerger<K, K2, V>(
|
|
67
|
-
key,
|
|
68
|
-
this.pointer,
|
|
69
|
-
this.memoryAllocatorAddress,
|
|
70
|
-
this.defaultValue,
|
|
71
|
-
),
|
|
72
|
-
);
|
|
59
|
+
super.set(key, new KeyMerger<K, K2, V>(key, this.pointer, this.defaultValue));
|
|
73
60
|
}
|
|
74
61
|
}
|
|
75
62
|
}
|
|
@@ -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
|
+
}
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import { u256 } from 'as-bignum/assembly';
|
|
2
2
|
import { SafeMath } from '../types/SafeMath';
|
|
3
|
-
import { Address } from '../types/Address';
|
|
4
3
|
import { MemorySlotPointer } from '../memory/MemorySlotPointer';
|
|
5
4
|
import { Blockchain } from '../env';
|
|
6
5
|
|
|
7
6
|
@final
|
|
8
7
|
export class StoredU256 {
|
|
9
8
|
constructor(
|
|
10
|
-
public address: Address,
|
|
11
9
|
public pointer: u16,
|
|
12
10
|
public subPointer: MemorySlotPointer,
|
|
13
11
|
private defaultValue: u256,
|
|
14
|
-
) {
|
|
15
|
-
this._value = Blockchain.getStorageAt(
|
|
16
|
-
this.address,
|
|
17
|
-
this.pointer,
|
|
18
|
-
this.subPointer,
|
|
19
|
-
this.defaultValue,
|
|
20
|
-
);
|
|
21
|
-
}
|
|
12
|
+
) {}
|
|
22
13
|
|
|
23
14
|
private _value: u256 = u256.Zero;
|
|
24
15
|
|
|
@@ -33,13 +24,7 @@ export class StoredU256 {
|
|
|
33
24
|
public set value(value: u256) {
|
|
34
25
|
this._value = value;
|
|
35
26
|
|
|
36
|
-
Blockchain.setStorageAt(
|
|
37
|
-
this.address,
|
|
38
|
-
this.pointer,
|
|
39
|
-
this.subPointer,
|
|
40
|
-
this._value,
|
|
41
|
-
this.defaultValue,
|
|
42
|
-
);
|
|
27
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
43
28
|
}
|
|
44
29
|
|
|
45
30
|
@inline
|
|
@@ -53,13 +38,7 @@ export class StoredU256 {
|
|
|
53
38
|
this.ensureValue();
|
|
54
39
|
|
|
55
40
|
this._value = SafeMath.add(this._value, value);
|
|
56
|
-
Blockchain.setStorageAt(
|
|
57
|
-
this.address,
|
|
58
|
-
this.pointer,
|
|
59
|
-
this.subPointer,
|
|
60
|
-
this._value,
|
|
61
|
-
this.defaultValue,
|
|
62
|
-
);
|
|
41
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
63
42
|
|
|
64
43
|
return this;
|
|
65
44
|
}
|
|
@@ -70,13 +49,7 @@ export class StoredU256 {
|
|
|
70
49
|
this.ensureValue();
|
|
71
50
|
|
|
72
51
|
this._value = SafeMath.sub(this._value, value);
|
|
73
|
-
Blockchain.setStorageAt(
|
|
74
|
-
this.address,
|
|
75
|
-
this.pointer,
|
|
76
|
-
this.subPointer,
|
|
77
|
-
this._value,
|
|
78
|
-
this.defaultValue,
|
|
79
|
-
);
|
|
52
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
80
53
|
|
|
81
54
|
return this;
|
|
82
55
|
}
|
|
@@ -87,13 +60,7 @@ export class StoredU256 {
|
|
|
87
60
|
this.ensureValue();
|
|
88
61
|
|
|
89
62
|
this._value = SafeMath.mul(this._value, value);
|
|
90
|
-
Blockchain.setStorageAt(
|
|
91
|
-
this.address,
|
|
92
|
-
this.pointer,
|
|
93
|
-
this.subPointer,
|
|
94
|
-
this._value,
|
|
95
|
-
this.defaultValue,
|
|
96
|
-
);
|
|
63
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
97
64
|
|
|
98
65
|
return this;
|
|
99
66
|
}
|
|
@@ -152,13 +119,7 @@ export class StoredU256 {
|
|
|
152
119
|
this.ensureValue();
|
|
153
120
|
|
|
154
121
|
this._value = u256.shr(this._value, value);
|
|
155
|
-
Blockchain.setStorageAt(
|
|
156
|
-
this.address,
|
|
157
|
-
this.pointer,
|
|
158
|
-
this.subPointer,
|
|
159
|
-
this._value,
|
|
160
|
-
this.defaultValue,
|
|
161
|
-
);
|
|
122
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
162
123
|
|
|
163
124
|
return this;
|
|
164
125
|
}
|
|
@@ -169,13 +130,7 @@ export class StoredU256 {
|
|
|
169
130
|
this.ensureValue();
|
|
170
131
|
|
|
171
132
|
this._value = u256.and(this._value, value);
|
|
172
|
-
Blockchain.setStorageAt(
|
|
173
|
-
this.address,
|
|
174
|
-
this.pointer,
|
|
175
|
-
this.subPointer,
|
|
176
|
-
this._value,
|
|
177
|
-
this.defaultValue,
|
|
178
|
-
);
|
|
133
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
179
134
|
|
|
180
135
|
return this;
|
|
181
136
|
}
|
|
@@ -186,13 +141,7 @@ export class StoredU256 {
|
|
|
186
141
|
this.ensureValue();
|
|
187
142
|
|
|
188
143
|
this._value = u256.or(this._value, value);
|
|
189
|
-
Blockchain.setStorageAt(
|
|
190
|
-
this.address,
|
|
191
|
-
this.pointer,
|
|
192
|
-
this.subPointer,
|
|
193
|
-
this._value,
|
|
194
|
-
this.defaultValue,
|
|
195
|
-
);
|
|
144
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
196
145
|
|
|
197
146
|
return this;
|
|
198
147
|
}
|
|
@@ -203,13 +152,7 @@ export class StoredU256 {
|
|
|
203
152
|
this.ensureValue();
|
|
204
153
|
|
|
205
154
|
this._value = u256.xor(this._value, value);
|
|
206
|
-
Blockchain.setStorageAt(
|
|
207
|
-
this.address,
|
|
208
|
-
this.pointer,
|
|
209
|
-
this.subPointer,
|
|
210
|
-
this._value,
|
|
211
|
-
this.defaultValue,
|
|
212
|
-
);
|
|
155
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
213
156
|
|
|
214
157
|
return this;
|
|
215
158
|
}
|
|
@@ -231,13 +174,7 @@ export class StoredU256 {
|
|
|
231
174
|
value = u256.shr(value, 1);
|
|
232
175
|
}
|
|
233
176
|
|
|
234
|
-
Blockchain.setStorageAt(
|
|
235
|
-
this.address,
|
|
236
|
-
this.pointer,
|
|
237
|
-
this.subPointer,
|
|
238
|
-
this._value,
|
|
239
|
-
this.defaultValue,
|
|
240
|
-
);
|
|
177
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
241
178
|
|
|
242
179
|
return this;
|
|
243
180
|
}
|
|
@@ -262,13 +199,7 @@ export class StoredU256 {
|
|
|
262
199
|
}
|
|
263
200
|
|
|
264
201
|
this._value = result;
|
|
265
|
-
Blockchain.setStorageAt(
|
|
266
|
-
this.address,
|
|
267
|
-
this.pointer,
|
|
268
|
-
this.subPointer,
|
|
269
|
-
this._value,
|
|
270
|
-
this.defaultValue,
|
|
271
|
-
);
|
|
202
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
272
203
|
|
|
273
204
|
return this;
|
|
274
205
|
}
|
|
@@ -279,13 +210,7 @@ export class StoredU256 {
|
|
|
279
210
|
this.ensureValue();
|
|
280
211
|
|
|
281
212
|
this._value = SafeMath.add(this._value, u256.One);
|
|
282
|
-
Blockchain.setStorageAt(
|
|
283
|
-
this.address,
|
|
284
|
-
this.pointer,
|
|
285
|
-
this.subPointer,
|
|
286
|
-
this._value,
|
|
287
|
-
this.defaultValue,
|
|
288
|
-
);
|
|
213
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
289
214
|
|
|
290
215
|
return this;
|
|
291
216
|
}
|
|
@@ -296,13 +221,7 @@ export class StoredU256 {
|
|
|
296
221
|
this.ensureValue();
|
|
297
222
|
|
|
298
223
|
this._value = SafeMath.sub(this._value, u256.One);
|
|
299
|
-
Blockchain.setStorageAt(
|
|
300
|
-
this.address,
|
|
301
|
-
this.pointer,
|
|
302
|
-
this.subPointer,
|
|
303
|
-
this._value,
|
|
304
|
-
this.defaultValue,
|
|
305
|
-
);
|
|
224
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
306
225
|
|
|
307
226
|
return this;
|
|
308
227
|
}
|
|
@@ -311,13 +230,7 @@ export class StoredU256 {
|
|
|
311
230
|
public set(value: u256): this {
|
|
312
231
|
this._value = value;
|
|
313
232
|
|
|
314
|
-
Blockchain.setStorageAt(
|
|
315
|
-
this.address,
|
|
316
|
-
this.pointer,
|
|
317
|
-
this.subPointer,
|
|
318
|
-
this._value,
|
|
319
|
-
this.defaultValue,
|
|
320
|
-
);
|
|
233
|
+
Blockchain.setStorageAt(this.pointer, this.subPointer, this._value);
|
|
321
234
|
|
|
322
235
|
return this;
|
|
323
236
|
}
|
|
@@ -328,11 +241,6 @@ export class StoredU256 {
|
|
|
328
241
|
}
|
|
329
242
|
|
|
330
243
|
private ensureValue(): void {
|
|
331
|
-
this._value = Blockchain.getStorageAt(
|
|
332
|
-
this.address,
|
|
333
|
-
this.pointer,
|
|
334
|
-
this.subPointer,
|
|
335
|
-
this.defaultValue,
|
|
336
|
-
);
|
|
244
|
+
this._value = Blockchain.getStorageAt(this.pointer, this.subPointer, this.defaultValue);
|
|
337
245
|
}
|
|
338
246
|
}
|
|
@@ -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
|
}
|