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