@btc-vision/btc-runtime 1.4.7 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +44 -53
- package/runtime/abort/abort.ts +25 -0
- package/runtime/buffer/BytesReader.ts +171 -140
- package/runtime/buffer/BytesWriter.ts +120 -152
- package/runtime/contracts/DeployableOP_20.ts +29 -15
- package/runtime/contracts/OP_NET.ts +1 -1
- package/runtime/env/BlockchainEnvironment.ts +79 -137
- package/runtime/env/classes/Block.ts +4 -8
- package/runtime/env/classes/Transaction.ts +14 -7
- package/runtime/env/classes/UTXO.ts +4 -2
- package/runtime/env/global.ts +49 -20
- package/runtime/events/predefined/MintEvent.ts +1 -1
- package/runtime/exports/index.ts +29 -8
- package/runtime/generic/AddressMap.ts +7 -5
- package/runtime/generic/Map.ts +32 -2
- package/runtime/generic/MapU256.ts +7 -5
- package/runtime/generic/MapUint8Array.ts +93 -0
- package/runtime/index.ts +4 -12
- package/runtime/math/abi.ts +71 -11
- package/runtime/math/bytes.ts +177 -41
- package/runtime/memory/AddressMemoryMap.ts +22 -19
- package/runtime/memory/FastUint8Array.ts +122 -0
- package/runtime/memory/KeyMerger.ts +25 -23
- package/runtime/memory/MultiAddressMemoryMap.ts +11 -8
- package/runtime/memory/MultiStringMemoryMap.ts +8 -5
- package/runtime/memory/StringMemoryMap.ts +15 -15
- package/runtime/memory/Uint8ArrayMerger.ts +22 -15
- package/runtime/storage/Serializable.ts +19 -20
- package/runtime/storage/StoredAddress.ts +16 -15
- package/runtime/storage/StoredBoolean.ts +26 -21
- package/runtime/storage/StoredString.ts +158 -102
- package/runtime/storage/StoredU256.ts +25 -28
- package/runtime/storage/StoredU64.ts +23 -35
- package/runtime/storage/arrays/StoredAddressArray.ts +83 -175
- package/runtime/storage/arrays/StoredBooleanArray.ts +146 -271
- package/runtime/storage/arrays/StoredPackedArray.ts +313 -0
- package/runtime/storage/arrays/StoredU128Array.ts +38 -374
- package/runtime/storage/arrays/StoredU16Array.ts +34 -420
- package/runtime/storage/arrays/StoredU256Array.ts +21 -347
- package/runtime/storage/arrays/StoredU32Array.ts +37 -440
- package/runtime/storage/arrays/StoredU64Array.ts +66 -0
- package/runtime/storage/arrays/StoredU8Array.ts +29 -453
- package/runtime/types/Address.ts +72 -5
- package/runtime/types/index.ts +1 -4
- package/runtime/utils/encodings.ts +5 -6
- package/runtime/utils/hex.ts +1 -1
- package/runtime/interfaces/DeployContractResponse.ts +0 -12
- package/runtime/math/cyrb53.ts +0 -48
- package/runtime/math/sha256.ts +0 -12
- package/runtime/memory/MemorySlot.ts +0 -1
- package/runtime/memory/MemorySlotPointer.ts +0 -3
- package/runtime/storage/utils/StorageBacked.ts +0 -5
- package/runtime/storage/utils/StorageLayout.ts +0 -7
- package/runtime/storage/utils/StorageSlot.ts +0 -106
- package/runtime/storage/utils/StorageStruct.ts +0 -23
- package/runtime/storage/utils/StorageValue.ts +0 -36
- package/runtime/tests/assert.ts +0 -11
- package/runtime/tests/env.ts +0 -7
- package/runtime/tests/tests.ts +0 -28
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { i128, u128, u256 } from '@btc-vision/as-bignum/assembly';
|
|
2
|
-
import { ArrayBuffer } from 'arraybuffer';
|
|
3
2
|
import { AddressMap } from '../generic/AddressMap';
|
|
4
3
|
import { Selector } from '../math/abi';
|
|
5
4
|
import { Address } from '../types/Address';
|
|
@@ -20,7 +19,6 @@ import { BytesReader } from './BytesReader';
|
|
|
20
19
|
export class BytesWriter {
|
|
21
20
|
private currentOffset: u32 = 0;
|
|
22
21
|
private buffer: DataView;
|
|
23
|
-
|
|
24
22
|
private readonly typedArray: Uint8Array;
|
|
25
23
|
|
|
26
24
|
constructor(length: i32) {
|
|
@@ -38,96 +36,144 @@ export class BytesWriter {
|
|
|
38
36
|
this.currentOffset += U8_BYTE_LENGTH;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Writes a 16-bit unsigned integer. By default big-endian (be = true).
|
|
41
|
+
* If be=false, writes little-endian.
|
|
42
|
+
*/
|
|
43
|
+
public writeU16(value: u16, be: boolean = true): void {
|
|
42
44
|
this.allocSafe(U16_BYTE_LENGTH);
|
|
43
|
-
this.buffer.setUint16(this.currentOffset, value,
|
|
45
|
+
this.buffer.setUint16(this.currentOffset, value, !be);
|
|
44
46
|
this.currentOffset += U16_BYTE_LENGTH;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Writes a 32-bit unsigned integer. By default big-endian (be = true).
|
|
51
|
+
*/
|
|
52
|
+
public writeU32(value: u32, be: boolean = true): void {
|
|
48
53
|
this.allocSafe(U32_BYTE_LENGTH);
|
|
49
|
-
this.buffer.setUint32(this.currentOffset, value,
|
|
54
|
+
this.buffer.setUint32(this.currentOffset, value, !be);
|
|
50
55
|
this.currentOffset += U32_BYTE_LENGTH;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Writes a 64-bit unsigned integer. By default big-endian (be = true).
|
|
60
|
+
*/
|
|
61
|
+
public writeU64(value: u64, be: boolean = true): void {
|
|
54
62
|
this.allocSafe(U64_BYTE_LENGTH);
|
|
55
|
-
this.buffer.setUint64(this.currentOffset, value || 0,
|
|
63
|
+
this.buffer.setUint64(this.currentOffset, value || 0, !be);
|
|
56
64
|
this.currentOffset += U64_BYTE_LENGTH;
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
for (let i: i32 = 0; i < value.length; i++) {
|
|
65
|
-
this.writeAddress(value[i]);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Writes a 32-bit selector.
|
|
69
|
+
* @param value
|
|
70
|
+
*/
|
|
69
71
|
public writeSelector(value: Selector): void {
|
|
70
|
-
this.writeU32(value,
|
|
72
|
+
this.writeU32(value, true);
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
public writeBoolean(value: boolean): void {
|
|
74
76
|
this.writeU8(value ? 1 : 0);
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
public writeU256(value: u256): void {
|
|
79
|
+
/**
|
|
80
|
+
* Writes a 256-bit unsigned integer. By default big-endian (be = true).
|
|
81
|
+
*/
|
|
82
|
+
public writeU256(value: u256, be: boolean = true): void {
|
|
82
83
|
this.allocSafe(U256_BYTE_LENGTH);
|
|
83
|
-
|
|
84
|
-
const bytes = value.toUint8Array(true);
|
|
84
|
+
const bytes = value.toUint8Array(be);
|
|
85
85
|
for (let i: i32 = 0; i < U256_BYTE_LENGTH; i++) {
|
|
86
|
-
this.writeU8(bytes[i]
|
|
86
|
+
this.writeU8(bytes[i]);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Writes a 128-bit signed integer. By default big-endian (be = true).
|
|
92
|
+
*/
|
|
93
|
+
public writeI128(value: i128, be: boolean = true): void {
|
|
91
94
|
this.allocSafe(I128_BYTE_LENGTH);
|
|
92
|
-
|
|
93
|
-
const bytes = value.toUint8Array(true);
|
|
95
|
+
const bytes = value.toUint8Array(be);
|
|
94
96
|
for (let i: i32 = 0; i < I128_BYTE_LENGTH; i++) {
|
|
95
|
-
this.writeU8(bytes[i]
|
|
97
|
+
this.writeU8(bytes[i]);
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Writes a 128-bit unsigned integer. By default big-endian (be = true).
|
|
103
|
+
*/
|
|
104
|
+
public writeU128(value: u128, be: boolean = true): void {
|
|
100
105
|
this.allocSafe(U128_BYTE_LENGTH);
|
|
101
|
-
|
|
102
|
-
const bytes = value.toUint8Array(true);
|
|
106
|
+
const bytes = value.toUint8Array(be);
|
|
103
107
|
for (let i: i32 = 0; i < U128_BYTE_LENGTH; i++) {
|
|
104
|
-
this.writeU8(bytes[i]
|
|
108
|
+
this.writeU8(bytes[i]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ------------------ Array Writers ------------------ //
|
|
113
|
+
|
|
114
|
+
public writeU16Array(value: u16[], be: boolean = true): void {
|
|
115
|
+
if (value.length > 65535) throw new Revert('Array size is too large');
|
|
116
|
+
this.allocSafe(U16_BYTE_LENGTH + value.length * U16_BYTE_LENGTH);
|
|
117
|
+
this.writeU16(u16(value.length), be);
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < value.length; i++) {
|
|
120
|
+
this.writeU16(value[i], be);
|
|
105
121
|
}
|
|
106
122
|
}
|
|
107
123
|
|
|
108
|
-
public
|
|
109
|
-
|
|
110
|
-
this.
|
|
124
|
+
public writeU32Array(value: u32[], be: boolean = true): void {
|
|
125
|
+
if (value.length > 65535) throw new Revert('Array size is too large');
|
|
126
|
+
this.allocSafe(U16_BYTE_LENGTH + value.length * U32_BYTE_LENGTH);
|
|
127
|
+
this.writeU16(u16(value.length), be);
|
|
111
128
|
|
|
112
129
|
for (let i = 0; i < value.length; i++) {
|
|
113
|
-
this.
|
|
130
|
+
this.writeU32(value[i], be);
|
|
114
131
|
}
|
|
115
132
|
}
|
|
116
133
|
|
|
117
|
-
public
|
|
134
|
+
public writeU64Array(value: u64[], be: boolean = true): void {
|
|
118
135
|
if (value.length > 65535) throw new Revert('Array size is too large');
|
|
136
|
+
this.allocSafe(U16_BYTE_LENGTH + value.length * U64_BYTE_LENGTH);
|
|
137
|
+
this.writeU16(u16(value.length), be);
|
|
138
|
+
|
|
139
|
+
for (let i = 0; i < value.length; i++) {
|
|
140
|
+
this.writeU64(value[i], be);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
119
143
|
|
|
144
|
+
public writeU128Array(value: u128[], be: boolean = true): void {
|
|
145
|
+
if (value.length > 65535) throw new Revert('Array size is too large');
|
|
120
146
|
this.allocSafe(U16_BYTE_LENGTH + value.length * U128_BYTE_LENGTH);
|
|
121
|
-
this.writeU16(u16(value.length));
|
|
147
|
+
this.writeU16(u16(value.length), be);
|
|
122
148
|
|
|
123
149
|
for (let i = 0; i < value.length; i++) {
|
|
124
|
-
this.writeU128(value[i]);
|
|
150
|
+
this.writeU128(value[i], be);
|
|
125
151
|
}
|
|
126
152
|
}
|
|
127
153
|
|
|
154
|
+
public writeU256Array(value: u256[], be: boolean = true): void {
|
|
155
|
+
if (value.length > 65535) throw new Revert('Array size is too large');
|
|
156
|
+
this.allocSafe(U16_BYTE_LENGTH + value.length * U256_BYTE_LENGTH);
|
|
157
|
+
this.writeU16(u16(value.length), be);
|
|
158
|
+
|
|
159
|
+
for (let i = 0; i < value.length; i++) {
|
|
160
|
+
this.writeU256(value[i], be);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public writeAddressArray(value: Address[]): void {
|
|
165
|
+
if (value.length > 65535) throw new Revert('Array size is too large');
|
|
166
|
+
this.writeU16(u16(value.length));
|
|
167
|
+
|
|
168
|
+
for (let i: i32 = 0; i < value.length; i++) {
|
|
169
|
+
this.writeAddress(value[i]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// --------------------------------------------------- //
|
|
174
|
+
|
|
128
175
|
public writeBytes(value: Uint8Array): void {
|
|
129
176
|
this.allocSafe(value.length);
|
|
130
|
-
|
|
131
177
|
for (let i = 0; i < value.length; i++) {
|
|
132
178
|
this.writeU8(value[i]);
|
|
133
179
|
}
|
|
@@ -136,18 +182,19 @@ export class BytesWriter {
|
|
|
136
182
|
@inline
|
|
137
183
|
public writeBytesU8Array(value: u8[]): void {
|
|
138
184
|
this.allocSafe(value.length);
|
|
139
|
-
|
|
140
185
|
for (let i = 0; i < value.length; i++) {
|
|
141
186
|
this.writeU8(value[i]);
|
|
142
187
|
}
|
|
143
188
|
}
|
|
144
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Writes [u32 length][raw bytes].
|
|
192
|
+
* By default big-endian, so length is stored with `writeU32(length, true)`.
|
|
193
|
+
*/
|
|
145
194
|
public writeBytesWithLength(value: Uint8Array): void {
|
|
146
195
|
const length: u32 = u32(value.length);
|
|
147
|
-
|
|
148
196
|
this.allocSafe(length + U32_BYTE_LENGTH);
|
|
149
|
-
this.writeU32(length);
|
|
150
|
-
|
|
197
|
+
this.writeU32(length); // default be = true => big-endian
|
|
151
198
|
for (let i: u32 = 0; i < length; i++) {
|
|
152
199
|
this.writeU8(value[i]);
|
|
153
200
|
}
|
|
@@ -166,80 +213,25 @@ export class BytesWriter {
|
|
|
166
213
|
|
|
167
214
|
public writeStringWithLength(value: string): void {
|
|
168
215
|
this.writeU16(u16(value.length));
|
|
169
|
-
|
|
170
216
|
this.writeString(value);
|
|
171
217
|
}
|
|
172
218
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Equivalent to TS’s writeAddressValueTuple, except specialized for u256 values.
|
|
221
|
+
*/
|
|
222
|
+
public writeAddressMapU256(value: AddressMap<u256>, be: boolean = true): void {
|
|
223
|
+
const keys: Address[] = value.keys();
|
|
224
|
+
if (keys.length > 65535) throw new Revert('Map size is too large');
|
|
177
225
|
|
|
178
|
-
|
|
179
|
-
abort(
|
|
180
|
-
`This buffer is too small. Required size: ${requiredSize} - Current size: ${this.buffer.byteLength}`,
|
|
181
|
-
);
|
|
182
|
-
}*/
|
|
183
|
-
|
|
184
|
-
this.writeU16(u16(map.size));
|
|
185
|
-
|
|
186
|
-
const keys = map.keys();
|
|
187
|
-
for (let i = 0; i < keys.length; i++) {
|
|
188
|
-
const key: Address = keys[i];
|
|
189
|
-
const value: u256 = map.get(key) || u256.Zero;
|
|
190
|
-
|
|
191
|
-
this.writeAddress(key);
|
|
192
|
-
this.writeU256(value);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
public writeLimitedAddressBytesMap(map: AddressMap<Uint8Array[]>): void {
|
|
197
|
-
if (map.size > 8) throw new Revert('Too many contract called.'); // no more than 8 different contracts.
|
|
198
|
-
|
|
199
|
-
/*let requiredSize: u32 = U8_BYTE_LENGTH + (map.size * ADDRESS_BYTE_LENGTH + U8_BYTE_LENGTH);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
for (let i = 0; i < map.size; i++) {
|
|
203
|
-
const address: Address = keys[i];
|
|
204
|
-
const calls: Uint8Array[] = map.get(address) || [];
|
|
205
|
-
|
|
206
|
-
for (let j: i32 = 0; j < calls.length; j++) {
|
|
207
|
-
requiredSize += 4 + calls[j].length;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (this.buffer.byteLength < requiredSize) {
|
|
212
|
-
abort(
|
|
213
|
-
`This buffer is too small. Required size: ${requiredSize} - Current size: ${this.buffer.byteLength}`,
|
|
214
|
-
);
|
|
215
|
-
}*/
|
|
216
|
-
|
|
217
|
-
const keys: Address[] = map.keys();
|
|
218
|
-
|
|
219
|
-
this.writeU8(u8(map.size));
|
|
226
|
+
this.writeU16(u16(keys.length), be);
|
|
220
227
|
|
|
221
228
|
for (let i: i32 = 0; i < keys.length; i++) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (calls.length > 10) throw new Revert('Too many calls.'); // no more than 16 different calls.
|
|
226
|
-
|
|
227
|
-
this.writeAddress(address);
|
|
228
|
-
this.writeU8(u8(calls.length));
|
|
229
|
-
|
|
230
|
-
for (let j: i32 = 0; j < calls.length; j++) {
|
|
231
|
-
this.writeBytesWithLength(calls[j]);
|
|
232
|
-
}
|
|
229
|
+
this.writeAddress(keys[i]);
|
|
230
|
+
this.writeU256(value.get(keys[i]), be);
|
|
233
231
|
}
|
|
234
232
|
}
|
|
235
233
|
|
|
236
|
-
|
|
237
|
-
this.writeU16(u16(map.length));
|
|
238
|
-
|
|
239
|
-
for (let i = 0; i < map.length; i++) {
|
|
240
|
-
this.writeSelector(map[i]);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
234
|
+
// --------------------------------------------------- //
|
|
243
235
|
|
|
244
236
|
public getBuffer(): Uint8Array {
|
|
245
237
|
return this.typedArray;
|
|
@@ -257,61 +249,37 @@ export class BytesWriter {
|
|
|
257
249
|
this.currentOffset = offset;
|
|
258
250
|
}
|
|
259
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Ensures we have space for `size` more bytes without going past the current buffer.
|
|
254
|
+
* If not, calls `resize()` which by default throws a Revert.
|
|
255
|
+
*/
|
|
260
256
|
public allocSafe(size: u32): void {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
257
|
+
const needed = this.currentOffset + size;
|
|
258
|
+
if (needed > u32(this.buffer.byteLength)) {
|
|
259
|
+
const sizeDiff: u32 = needed - u32(this.buffer.byteLength);
|
|
264
260
|
this.resize(sizeDiff);
|
|
265
261
|
}
|
|
266
262
|
}
|
|
267
263
|
|
|
268
|
-
public writeABISelector(name: string, selector: Selector): void {
|
|
269
|
-
this.writeStringWithLength(name);
|
|
270
|
-
this.writeSelector(selector);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
private writeMethodSelectorMap(value: Set<Selector>): void {
|
|
274
|
-
this.writeU16(u16(value.size));
|
|
275
|
-
|
|
276
|
-
const keys = value.values();
|
|
277
|
-
for (let i = 0; i < keys.length; i++) {
|
|
278
|
-
const key = keys[i];
|
|
279
|
-
|
|
280
|
-
this.writeSelector(key);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
private min(value1: i32, value2: i32): i32 {
|
|
285
|
-
return value1 < value2 ? value1 : value2;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
264
|
private fromAddress(pubKey: Address): Uint8Array {
|
|
289
265
|
if (pubKey.byteLength > ADDRESS_BYTE_LENGTH) {
|
|
290
266
|
throw new Revert(
|
|
291
267
|
`Address is too long ${pubKey.byteLength} > ${ADDRESS_BYTE_LENGTH} bytes`,
|
|
292
268
|
);
|
|
293
269
|
}
|
|
294
|
-
|
|
295
270
|
return pubKey;
|
|
296
271
|
}
|
|
297
272
|
|
|
273
|
+
/**
|
|
274
|
+
* This implementation always throws rather than actually resizing,
|
|
275
|
+
* which is consistent with the original approach. If you need
|
|
276
|
+
* dynamic resizing, remove the `throw` and implement accordingly.
|
|
277
|
+
*/
|
|
298
278
|
private resize(size: u32): void {
|
|
299
|
-
|
|
300
|
-
`Buffer is getting resized. This is
|
|
301
|
-
|
|
302
|
-
|
|
279
|
+
throw new Revert(
|
|
280
|
+
`Buffer is getting resized. This is bad for performance. ` +
|
|
281
|
+
`Expected size: ${this.buffer.byteLength + size} - ` +
|
|
282
|
+
`Current size: ${this.buffer.byteLength}`,
|
|
303
283
|
);
|
|
304
|
-
|
|
305
|
-
/*const buf: Uint8Array = new Uint8Array(u32(this.buffer.byteLength) + size);
|
|
306
|
-
|
|
307
|
-
for (let i: i32 = 0; i < this.buffer.byteLength; i++) {
|
|
308
|
-
buf[i] = this.buffer.getUint8(i);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
this.buffer = new DataView(buf.buffer);*/
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
private getDefaultBuffer(length: i32 = 1): DataView {
|
|
315
|
-
return new DataView(new ArrayBuffer(length));
|
|
316
284
|
}
|
|
317
285
|
}
|
|
@@ -11,46 +11,46 @@ import { Address } from '../types/Address';
|
|
|
11
11
|
import { Revert } from '../types/Revert';
|
|
12
12
|
import { SafeMath } from '../types/SafeMath';
|
|
13
13
|
|
|
14
|
+
import { ApproveStr, TransferFromStr, TransferStr } from '../shared-libraries/TransferHelper';
|
|
14
15
|
import { Calldata } from '../types';
|
|
15
16
|
import { ADDRESS_BYTE_LENGTH, BOOLEAN_BYTE_LENGTH, U256_BYTE_LENGTH } from '../utils';
|
|
16
17
|
import { IOP_20 } from './interfaces/IOP_20';
|
|
17
18
|
import { OP20InitParameters } from './interfaces/OP20InitParameters';
|
|
18
19
|
import { OP_NET } from './OP_NET';
|
|
19
20
|
import { sha256 } from '../env/global';
|
|
20
|
-
import {
|
|
21
|
+
import { EMPTY_POINTER } from '../math/bytes';
|
|
21
22
|
|
|
22
23
|
const nonceMapPointer: u16 = Blockchain.nextPointer;
|
|
23
24
|
const maxSupplyPointer: u16 = Blockchain.nextPointer;
|
|
24
25
|
const decimalsPointer: u16 = Blockchain.nextPointer;
|
|
25
|
-
const
|
|
26
|
-
const symbolPointer: u16 = Blockchain.nextPointer;
|
|
26
|
+
const stringPointer: u16 = Blockchain.nextPointer;
|
|
27
27
|
const totalSupplyPointer: u16 = Blockchain.nextPointer;
|
|
28
28
|
const allowanceMapPointer: u16 = Blockchain.nextPointer;
|
|
29
29
|
const balanceOfMapPointer: u16 = Blockchain.nextPointer;
|
|
30
30
|
|
|
31
31
|
export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
32
|
-
protected readonly allowanceMap: MultiAddressMemoryMap
|
|
33
|
-
protected readonly balanceOfMap: AddressMemoryMap
|
|
32
|
+
protected readonly allowanceMap: MultiAddressMemoryMap;
|
|
33
|
+
protected readonly balanceOfMap: AddressMemoryMap;
|
|
34
34
|
|
|
35
35
|
protected readonly _maxSupply: StoredU256;
|
|
36
36
|
protected readonly _decimals: StoredU256;
|
|
37
37
|
protected readonly _name: StoredString;
|
|
38
38
|
protected readonly _symbol: StoredString;
|
|
39
39
|
|
|
40
|
-
protected readonly _nonceMap: AddressMemoryMap
|
|
40
|
+
protected readonly _nonceMap: AddressMemoryMap;
|
|
41
41
|
|
|
42
42
|
protected constructor(params: OP20InitParameters | null = null) {
|
|
43
43
|
super();
|
|
44
44
|
|
|
45
45
|
// Initialize main storage structures
|
|
46
|
-
this.allowanceMap = new MultiAddressMemoryMap
|
|
47
|
-
this.balanceOfMap = new AddressMemoryMap
|
|
48
|
-
this._totalSupply = new StoredU256(totalSupplyPointer,
|
|
49
|
-
this._maxSupply = new StoredU256(maxSupplyPointer,
|
|
50
|
-
this._decimals = new StoredU256(decimalsPointer,
|
|
51
|
-
this._name = new StoredString(
|
|
52
|
-
this._symbol = new StoredString(
|
|
53
|
-
this._nonceMap = new AddressMemoryMap(nonceMapPointer
|
|
46
|
+
this.allowanceMap = new MultiAddressMemoryMap(allowanceMapPointer);
|
|
47
|
+
this.balanceOfMap = new AddressMemoryMap(balanceOfMapPointer);
|
|
48
|
+
this._totalSupply = new StoredU256(totalSupplyPointer, EMPTY_POINTER);
|
|
49
|
+
this._maxSupply = new StoredU256(maxSupplyPointer, EMPTY_POINTER);
|
|
50
|
+
this._decimals = new StoredU256(decimalsPointer, EMPTY_POINTER);
|
|
51
|
+
this._name = new StoredString(stringPointer, 0);
|
|
52
|
+
this._symbol = new StoredString(stringPointer, 1);
|
|
53
|
+
this._nonceMap = new AddressMemoryMap(nonceMapPointer);
|
|
54
54
|
|
|
55
55
|
if (params && this._maxSupply.value.isZero()) {
|
|
56
56
|
this.instantiate(params, true);
|
|
@@ -121,6 +121,13 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
public approveFrom(callData: Calldata): BytesWriter {
|
|
124
|
+
// If the transaction is initiated directly by the owner, there is no need for an off-chain signature.
|
|
125
|
+
if (Blockchain.tx.origin == Blockchain.tx.sender) {
|
|
126
|
+
throw new Revert(
|
|
127
|
+
'Direct owner approval detected. Use approve function instead of approveFrom.',
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
124
131
|
const response = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
125
132
|
|
|
126
133
|
const owner: Address = Blockchain.tx.origin;
|
|
@@ -155,8 +162,10 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
155
162
|
public balanceOf(callData: Calldata): BytesWriter {
|
|
156
163
|
const response = new BytesWriter(U256_BYTE_LENGTH);
|
|
157
164
|
const address: Address = callData.readAddress();
|
|
165
|
+
|
|
158
166
|
const resp = this._balanceOf(address);
|
|
159
167
|
response.writeU256(resp);
|
|
168
|
+
|
|
160
169
|
return response;
|
|
161
170
|
}
|
|
162
171
|
|
|
@@ -164,6 +173,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
164
173
|
const response = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
165
174
|
const resp = this._burn(callData.readU256());
|
|
166
175
|
response.writeBoolean(resp);
|
|
176
|
+
|
|
167
177
|
return response;
|
|
168
178
|
}
|
|
169
179
|
|
|
@@ -171,6 +181,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
171
181
|
const response = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
172
182
|
const resp = this._transfer(callData.readAddress(), callData.readU256());
|
|
173
183
|
response.writeBoolean(resp);
|
|
184
|
+
|
|
174
185
|
return response;
|
|
175
186
|
}
|
|
176
187
|
|
|
@@ -181,6 +192,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
181
192
|
callData.readAddress(),
|
|
182
193
|
callData.readU256(),
|
|
183
194
|
);
|
|
195
|
+
|
|
184
196
|
response.writeBoolean(resp);
|
|
185
197
|
return response;
|
|
186
198
|
}
|
|
@@ -213,7 +225,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
213
225
|
return this.allowance(calldata);
|
|
214
226
|
case encodeSelector(ApproveStr):
|
|
215
227
|
return this.approve(calldata);
|
|
216
|
-
case encodeSelector('approveFrom(address,uint256,
|
|
228
|
+
case encodeSelector('approveFrom(address,uint256,uint256,bytes)'):
|
|
217
229
|
return this.approveFrom(calldata);
|
|
218
230
|
case encodeSelector('balanceOf(address)'):
|
|
219
231
|
return this.balanceOf(calldata);
|
|
@@ -292,6 +304,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
292
304
|
if (owner === Blockchain.DEAD_ADDRESS) {
|
|
293
305
|
throw new Revert('Address can not be dead address');
|
|
294
306
|
}
|
|
307
|
+
|
|
295
308
|
if (spender === Blockchain.DEAD_ADDRESS) {
|
|
296
309
|
throw new Revert('Spender cannot be dead address');
|
|
297
310
|
}
|
|
@@ -305,6 +318,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
305
318
|
|
|
306
319
|
protected _balanceOf(owner: Address): u256 {
|
|
307
320
|
if (!this.balanceOfMap.has(owner)) return u256.Zero;
|
|
321
|
+
|
|
308
322
|
return this.balanceOfMap.get(owner);
|
|
309
323
|
}
|
|
310
324
|
|