@btc-vision/btc-runtime 1.7.0 → 1.7.2
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btc-vision/btc-runtime",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "Bitcoin Smart Contract Runtime",
|
|
5
5
|
"main": "btc/index.ts",
|
|
6
6
|
"scripts": {},
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"author": "BlobMaster41",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@types/node": "^22.
|
|
21
|
-
"assemblyscript": "^0.
|
|
20
|
+
"@types/node": "^22.15.26",
|
|
21
|
+
"assemblyscript": "^0.28.1"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
@@ -35,12 +35,13 @@
|
|
|
35
35
|
"test/*.ts"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@assemblyscript/loader": "^0.
|
|
38
|
+
"@assemblyscript/loader": "^0.28.1",
|
|
39
39
|
"@btc-vision/as-bignum": "^0.0.5",
|
|
40
|
-
"@
|
|
40
|
+
"@btc-vision/opnet-transform": "^0.1.3",
|
|
41
|
+
"@eslint/js": "^9.27.0",
|
|
41
42
|
"gulplog": "^2.2.0",
|
|
42
43
|
"ts-node": "^10.9.2",
|
|
43
44
|
"typescript": "^5.8.3",
|
|
44
|
-
"typescript-eslint": "^8.
|
|
45
|
+
"typescript-eslint": "^8.33.0"
|
|
45
46
|
}
|
|
46
47
|
}
|
package/runtime/abort/abort.ts
CHANGED
|
@@ -7,19 +7,17 @@ export function revertOnError(message: string, fileName: string, line: u32, colu
|
|
|
7
7
|
|
|
8
8
|
const revertMessage = `${message} at ${fileName}:${line}:${column}`;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const length = u16(revertMessage.length);
|
|
12
|
-
const _length_i32 = i32(length);
|
|
10
|
+
const length = revertMessage.length;
|
|
13
11
|
|
|
14
|
-
const arrayBuffer = new ArrayBuffer(4 +
|
|
12
|
+
const arrayBuffer = new ArrayBuffer(4 + length + 4);
|
|
15
13
|
const writer = new DataView(arrayBuffer);
|
|
16
14
|
|
|
17
15
|
writer.setUint32(0, selector, false);
|
|
18
|
-
writer.
|
|
16
|
+
writer.setUint32(4, length, false);
|
|
19
17
|
|
|
20
|
-
for (let i = 0; i <
|
|
21
|
-
writer.setUint8(
|
|
18
|
+
for (let i = 0; i < length; i++) {
|
|
19
|
+
writer.setUint8(8 + i, <u8>revertMessage.charCodeAt(i));
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
env_exit(1, arrayBuffer, arrayBuffer.byteLength);
|
|
25
|
-
}
|
|
23
|
+
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { u256 } from '@btc-vision/as-bignum/assembly';
|
|
2
|
+
|
|
2
3
|
import { BytesWriter } from '../buffer/BytesWriter';
|
|
3
4
|
import { Blockchain } from '../env';
|
|
4
5
|
import { ApproveEvent, BurnEvent, MintEvent, TransferEvent } from '../events/predefined';
|
|
5
|
-
import { encodeSelector, Selector } from '../math/abi';
|
|
6
6
|
import { StoredString } from '../storage/StoredString';
|
|
7
7
|
import { StoredU256 } from '../storage/StoredU256';
|
|
8
8
|
import { Address } from '../types/Address';
|
|
9
9
|
import { Revert } from '../types/Revert';
|
|
10
10
|
import { SafeMath } from '../types/SafeMath';
|
|
11
|
-
|
|
12
11
|
import { sha256 } from '../env/global';
|
|
13
12
|
import { EMPTY_POINTER } from '../math/bytes';
|
|
14
13
|
import { AddressMemoryMap } from '../memory/AddressMemoryMap';
|
|
15
14
|
import { MapOfMap } from '../memory/MapOfMap';
|
|
16
|
-
import { ApproveStr, TransferFromStr, TransferStr } from '../shared-libraries/TransferHelper';
|
|
17
15
|
import { Calldata } from '../types';
|
|
18
16
|
import { ADDRESS_BYTE_LENGTH, BOOLEAN_BYTE_LENGTH, U256_BYTE_LENGTH } from '../utils';
|
|
19
17
|
import { IOP_20 } from './interfaces/IOP_20';
|
|
@@ -36,14 +34,12 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
36
34
|
protected readonly _decimals: StoredU256;
|
|
37
35
|
protected readonly _name: StoredString;
|
|
38
36
|
protected readonly _symbol: StoredString;
|
|
39
|
-
|
|
40
37
|
protected readonly _nonceMap: AddressMemoryMap;
|
|
41
38
|
|
|
42
39
|
public constructor(params: OP20InitParameters | null = null) {
|
|
43
40
|
super();
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
this.allowanceMap = new MapOfMap(allowanceMapPointer);
|
|
42
|
+
this.allowanceMap = new MapOfMap<u256>(allowanceMapPointer);
|
|
47
43
|
this.balanceOfMap = new AddressMemoryMap(balanceOfMapPointer);
|
|
48
44
|
this._nonceMap = new AddressMemoryMap(nonceMapPointer);
|
|
49
45
|
|
|
@@ -58,6 +54,7 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
58
54
|
}
|
|
59
55
|
}
|
|
60
56
|
|
|
57
|
+
/** Intentionally public for inherited classes */
|
|
61
58
|
public _totalSupply: StoredU256;
|
|
62
59
|
|
|
63
60
|
public get totalSupply(): u256 {
|
|
@@ -88,15 +85,9 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
88
85
|
params: OP20InitParameters,
|
|
89
86
|
skipDeployerVerification: boolean = false,
|
|
90
87
|
): void {
|
|
91
|
-
if (!this._maxSupply.value.isZero())
|
|
92
|
-
throw new Revert('Already initialized');
|
|
93
|
-
}
|
|
94
|
-
|
|
88
|
+
if (!this._maxSupply.value.isZero()) throw new Revert('Already initialized');
|
|
95
89
|
if (!skipDeployerVerification) this.onlyDeployer(Blockchain.tx.sender);
|
|
96
|
-
|
|
97
|
-
if (params.decimals > 32) {
|
|
98
|
-
throw new Revert('Decimals can not be more than 32');
|
|
99
|
-
}
|
|
90
|
+
if (params.decimals > 32) throw new Revert('Decimals > 32');
|
|
100
91
|
|
|
101
92
|
this._maxSupply.value = params.maxSupply;
|
|
102
93
|
this._decimals.value = u256.fromU32(u32(params.decimals));
|
|
@@ -104,153 +95,156 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
104
95
|
this._symbol.value = params.symbol;
|
|
105
96
|
}
|
|
106
97
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
return
|
|
98
|
+
@method('decimals')
|
|
99
|
+
@returns({ name: 'decimals', type: ABIDataTypes.UINT8 })
|
|
100
|
+
public fn_decimals(_: Calldata): BytesWriter {
|
|
101
|
+
const w = new BytesWriter(1);
|
|
102
|
+
w.writeU8(this.decimals);
|
|
103
|
+
return w;
|
|
113
104
|
}
|
|
114
105
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
106
|
+
@method('name')
|
|
107
|
+
@returns({ name: 'name', type: ABIDataTypes.STRING })
|
|
108
|
+
public fn_name(_: Calldata): BytesWriter {
|
|
109
|
+
const w = new BytesWriter(this.name.length + 4);
|
|
110
|
+
w.writeStringWithLength(this.name);
|
|
111
|
+
return w;
|
|
112
|
+
}
|
|
119
113
|
|
|
120
|
-
|
|
114
|
+
@method('symbol')
|
|
115
|
+
@returns({ name: 'symbol', type: ABIDataTypes.STRING })
|
|
116
|
+
public fn_symbol(_: Calldata): BytesWriter {
|
|
117
|
+
const w = new BytesWriter(this.symbol.length + 4);
|
|
118
|
+
w.writeStringWithLength(this.symbol);
|
|
119
|
+
return w;
|
|
120
|
+
}
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
@method('totalSupply')
|
|
123
|
+
@returns({ name: 'totalSupply', type: ABIDataTypes.UINT256 })
|
|
124
|
+
public fn_totalSupply(_: Calldata): BytesWriter {
|
|
125
|
+
const w = new BytesWriter(U256_BYTE_LENGTH);
|
|
126
|
+
w.writeU256(this.totalSupply);
|
|
127
|
+
return w;
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
@method('maximumSupply')
|
|
131
|
+
@returns({ name: 'maximumSupply', type: ABIDataTypes.UINT256 })
|
|
132
|
+
public fn_maximumSupply(_: Calldata): BytesWriter {
|
|
133
|
+
const w = new BytesWriter(U256_BYTE_LENGTH);
|
|
134
|
+
w.writeU256(this.maxSupply);
|
|
135
|
+
return w;
|
|
136
|
+
}
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
@method(
|
|
139
|
+
{ name: 'owner', type: ABIDataTypes.ADDRESS },
|
|
140
|
+
{ name: 'spender', type: ABIDataTypes.ADDRESS },
|
|
141
|
+
)
|
|
142
|
+
@returns({ name: 'remaining', type: ABIDataTypes.UINT256 })
|
|
143
|
+
public allowance(calldata: Calldata): BytesWriter {
|
|
144
|
+
const w = new BytesWriter(U256_BYTE_LENGTH);
|
|
145
|
+
const rem = this._allowance(calldata.readAddress(), calldata.readAddress());
|
|
146
|
+
w.writeU256(rem);
|
|
147
|
+
return w;
|
|
148
|
+
}
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
@method(
|
|
151
|
+
{ name: 'spender', type: ABIDataTypes.ADDRESS },
|
|
152
|
+
{ name: 'amount', type: ABIDataTypes.UINT256 },
|
|
153
|
+
)
|
|
154
|
+
@returns({ name: 'success', type: ABIDataTypes.BOOL })
|
|
155
|
+
@emit('Approve')
|
|
156
|
+
public approve(calldata: Calldata): BytesWriter {
|
|
157
|
+
const ok = this._approve(Blockchain.tx.sender, calldata.readAddress(), calldata.readU256());
|
|
158
|
+
const w = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
159
|
+
w.writeBoolean(ok);
|
|
160
|
+
return w;
|
|
161
|
+
}
|
|
141
162
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
163
|
+
@method(
|
|
164
|
+
{ name: 'spender', type: ABIDataTypes.ADDRESS },
|
|
165
|
+
{ name: 'amount', type: ABIDataTypes.UINT256 },
|
|
166
|
+
{ name: 'nonce', type: ABIDataTypes.UINT256 },
|
|
167
|
+
{ name: 'sig', type: ABIDataTypes.BYTES },
|
|
168
|
+
)
|
|
169
|
+
@returns({ name: 'success', type: ABIDataTypes.BOOL })
|
|
170
|
+
@emit('Approve')
|
|
171
|
+
public approveFrom(calldata: Calldata): BytesWriter {
|
|
172
|
+
if (Blockchain.tx.origin == Blockchain.tx.sender) {
|
|
173
|
+
throw new Revert('Direct owner approval – use approve()');
|
|
145
174
|
}
|
|
146
175
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
176
|
+
const owner: Address = Blockchain.tx.origin;
|
|
177
|
+
const spender: Address = calldata.readAddress();
|
|
178
|
+
const value: u256 = calldata.readU256();
|
|
179
|
+
const nonce: u256 = calldata.readU256();
|
|
180
|
+
const sig = calldata.readBytesWithLength();
|
|
181
|
+
if (sig.length !== 64) throw new Revert('Invalid signature length');
|
|
182
|
+
|
|
183
|
+
const ok = this._approveFrom(owner, spender, value, nonce, sig);
|
|
184
|
+
const w = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
185
|
+
w.writeBoolean(ok);
|
|
186
|
+
return w;
|
|
151
187
|
}
|
|
152
188
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const response = new BytesWriter(32);
|
|
161
|
-
response.writeU256(currentNonce);
|
|
162
|
-
|
|
163
|
-
return response;
|
|
189
|
+
@method({ name: 'owner', type: ABIDataTypes.ADDRESS })
|
|
190
|
+
@returns({ name: 'nonce', type: ABIDataTypes.UINT256 })
|
|
191
|
+
public nonceOf(calldata: Calldata): BytesWriter {
|
|
192
|
+
const current = this._nonceMap.get(calldata.readAddress());
|
|
193
|
+
const w = new BytesWriter(U256_BYTE_LENGTH);
|
|
194
|
+
w.writeU256(current);
|
|
195
|
+
return w;
|
|
164
196
|
}
|
|
165
197
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return response;
|
|
198
|
+
@method({ name: 'owner', type: ABIDataTypes.ADDRESS })
|
|
199
|
+
@returns({ name: 'balance', type: ABIDataTypes.UINT256 })
|
|
200
|
+
public balanceOf(calldata: Calldata): BytesWriter {
|
|
201
|
+
const bal = this._balanceOf(calldata.readAddress());
|
|
202
|
+
const w = new BytesWriter(U256_BYTE_LENGTH);
|
|
203
|
+
w.writeU256(bal);
|
|
204
|
+
return w;
|
|
174
205
|
}
|
|
175
206
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
@method({ name: 'amount', type: ABIDataTypes.UINT256 })
|
|
208
|
+
@returns({ name: 'success', type: ABIDataTypes.BOOL })
|
|
209
|
+
@emit('Burn')
|
|
210
|
+
public burn(calldata: Calldata): BytesWriter {
|
|
211
|
+
const ok = this._burn(calldata.readU256());
|
|
212
|
+
const w = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
213
|
+
w.writeBoolean(ok);
|
|
214
|
+
return w;
|
|
182
215
|
}
|
|
183
216
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
217
|
+
@method(
|
|
218
|
+
{ name: 'to', type: ABIDataTypes.ADDRESS },
|
|
219
|
+
{ name: 'amount', type: ABIDataTypes.UINT256 },
|
|
220
|
+
)
|
|
221
|
+
@returns({ name: 'success', type: ABIDataTypes.BOOL })
|
|
222
|
+
@emit('Transfer')
|
|
223
|
+
public transfer(calldata: Calldata): BytesWriter {
|
|
224
|
+
const ok = this._transfer(calldata.readAddress(), calldata.readU256());
|
|
225
|
+
const w = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
226
|
+
w.writeBoolean(ok);
|
|
227
|
+
return w;
|
|
190
228
|
}
|
|
191
229
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
230
|
+
@method(
|
|
231
|
+
{ name: 'from', type: ABIDataTypes.ADDRESS },
|
|
232
|
+
{ name: 'to', type: ABIDataTypes.ADDRESS },
|
|
233
|
+
{ name: 'amount', type: ABIDataTypes.UINT256 },
|
|
234
|
+
)
|
|
235
|
+
@returns({ name: 'success', type: ABIDataTypes.BOOL })
|
|
236
|
+
@emit('Transfer')
|
|
237
|
+
public transferFrom(calldata: Calldata): BytesWriter {
|
|
238
|
+
const ok = this._transferFrom(
|
|
239
|
+
calldata.readAddress(),
|
|
240
|
+
calldata.readAddress(),
|
|
241
|
+
calldata.readU256(),
|
|
198
242
|
);
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
public execute(method: Selector, calldata: Calldata): BytesWriter {
|
|
205
|
-
let response: BytesWriter;
|
|
206
|
-
|
|
207
|
-
switch (method) {
|
|
208
|
-
case encodeSelector('decimals()'):
|
|
209
|
-
response = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
210
|
-
response.writeU8(this.decimals);
|
|
211
|
-
break;
|
|
212
|
-
case encodeSelector('name()'):
|
|
213
|
-
response = new BytesWriter(this.name.length + 2);
|
|
214
|
-
response.writeStringWithLength(this.name);
|
|
215
|
-
break;
|
|
216
|
-
case encodeSelector('symbol()'):
|
|
217
|
-
response = new BytesWriter(this.symbol.length + 2);
|
|
218
|
-
response.writeStringWithLength(this.symbol);
|
|
219
|
-
break;
|
|
220
|
-
case encodeSelector('totalSupply()'):
|
|
221
|
-
response = new BytesWriter(U256_BYTE_LENGTH);
|
|
222
|
-
response.writeU256(this.totalSupply);
|
|
223
|
-
break;
|
|
224
|
-
case encodeSelector('maximumSupply()'):
|
|
225
|
-
response = new BytesWriter(U256_BYTE_LENGTH);
|
|
226
|
-
response.writeU256(this.maxSupply);
|
|
227
|
-
break;
|
|
228
|
-
case encodeSelector('allowance(address,address)'):
|
|
229
|
-
return this.allowance(calldata);
|
|
230
|
-
case encodeSelector(ApproveStr):
|
|
231
|
-
return this.approve(calldata);
|
|
232
|
-
case encodeSelector('approveFrom(address,uint256,uint256,bytes)'):
|
|
233
|
-
return this.approveFrom(calldata);
|
|
234
|
-
case encodeSelector('balanceOf(address)'):
|
|
235
|
-
return this.balanceOf(calldata);
|
|
236
|
-
case encodeSelector('burn(uint256)'):
|
|
237
|
-
return this.burn(calldata);
|
|
238
|
-
case encodeSelector(TransferStr):
|
|
239
|
-
return this.transfer(calldata);
|
|
240
|
-
case encodeSelector(TransferFromStr):
|
|
241
|
-
return this.transferFrom(calldata);
|
|
242
|
-
|
|
243
|
-
case encodeSelector('nonceOf(address)'):
|
|
244
|
-
return this.nonceOf(calldata);
|
|
245
|
-
|
|
246
|
-
default:
|
|
247
|
-
return super.execute(method, calldata);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return response;
|
|
243
|
+
const w = new BytesWriter(BOOLEAN_BYTE_LENGTH);
|
|
244
|
+
w.writeBoolean(ok);
|
|
245
|
+
return w;
|
|
251
246
|
}
|
|
252
247
|
|
|
253
|
-
/** REDEFINED METHODS */
|
|
254
248
|
protected _allowance(owner: Address, spender: Address): u256 {
|
|
255
249
|
const senderMap = this.allowanceMap.get(owner);
|
|
256
250
|
return senderMap.get(spender);
|
|
@@ -263,25 +257,15 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
263
257
|
nonce: u256,
|
|
264
258
|
signature: Uint8Array,
|
|
265
259
|
): boolean {
|
|
266
|
-
if (owner === Blockchain.DEAD_ADDRESS)
|
|
267
|
-
|
|
268
|
-
}
|
|
260
|
+
if (owner === Blockchain.DEAD_ADDRESS) throw new Revert('Address can not be dead');
|
|
261
|
+
if (spender === Blockchain.DEAD_ADDRESS) throw new Revert('Spender can not be dead');
|
|
269
262
|
|
|
270
|
-
if (spender === Blockchain.DEAD_ADDRESS) {
|
|
271
|
-
throw new Revert('Spender cannot be dead address');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Ensure the nonce matches what we have stored on-chain
|
|
275
263
|
const storedNonce = this._nonceMap.get(owner);
|
|
276
|
-
if (!u256.eq(storedNonce, nonce))
|
|
277
|
-
throw new Revert('Invalid nonce (possible replay or out-of-sync)');
|
|
278
|
-
}
|
|
264
|
+
if (!u256.eq(storedNonce, nonce)) throw new Revert('Invalid nonce');
|
|
279
265
|
|
|
280
|
-
// Build the hash to match exactly what the user signed, including the nonce
|
|
281
266
|
const writer = new BytesWriter(
|
|
282
267
|
ADDRESS_BYTE_LENGTH * 3 + U256_BYTE_LENGTH + U256_BYTE_LENGTH,
|
|
283
268
|
);
|
|
284
|
-
|
|
285
269
|
writer.writeAddress(owner);
|
|
286
270
|
writer.writeAddress(spender);
|
|
287
271
|
writer.writeU256(value);
|
|
@@ -290,29 +274,21 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
290
274
|
|
|
291
275
|
const hash = sha256(writer.getBuffer());
|
|
292
276
|
if (!Blockchain.verifySchnorrSignature(owner, signature, hash)) {
|
|
293
|
-
throw new Revert('
|
|
277
|
+
throw new Revert('Invalid signature');
|
|
294
278
|
}
|
|
295
279
|
|
|
296
|
-
// If valid, increment the nonce so this signature can't be reused
|
|
297
280
|
this._nonceMap.set(owner, SafeMath.add(storedNonce, u256.One));
|
|
298
281
|
|
|
299
|
-
// Update allowance
|
|
300
282
|
const senderMap = this.allowanceMap.get(owner);
|
|
301
283
|
senderMap.set(spender, value);
|
|
302
284
|
|
|
303
|
-
// Emit event
|
|
304
285
|
this.createApproveEvent(owner, spender, value);
|
|
305
286
|
return true;
|
|
306
287
|
}
|
|
307
288
|
|
|
308
289
|
protected _approve(owner: Address, spender: Address, value: u256): boolean {
|
|
309
|
-
if (owner === Blockchain.DEAD_ADDRESS)
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
if (spender === Blockchain.DEAD_ADDRESS) {
|
|
314
|
-
throw new Revert('Spender cannot be dead address');
|
|
315
|
-
}
|
|
290
|
+
if (owner === Blockchain.DEAD_ADDRESS) throw new Revert('Address can not be dead');
|
|
291
|
+
if (spender === Blockchain.DEAD_ADDRESS) throw new Revert('Spender can not be dead');
|
|
316
292
|
|
|
317
293
|
const senderMap = this.allowanceMap.get(owner);
|
|
318
294
|
senderMap.set(spender, value);
|
|
@@ -323,26 +299,23 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
323
299
|
|
|
324
300
|
protected _balanceOf(owner: Address): u256 {
|
|
325
301
|
if (!this.balanceOfMap.has(owner)) return u256.Zero;
|
|
326
|
-
|
|
327
302
|
return this.balanceOfMap.get(owner);
|
|
328
303
|
}
|
|
329
304
|
|
|
330
305
|
protected _burn(value: u256, onlyDeployer: boolean = true): boolean {
|
|
331
|
-
if (u256.eq(value, u256.Zero))
|
|
332
|
-
throw new Revert(`No tokens`);
|
|
333
|
-
}
|
|
306
|
+
if (u256.eq(value, u256.Zero)) throw new Revert('No tokens');
|
|
334
307
|
|
|
335
308
|
if (onlyDeployer) this.onlyDeployer(Blockchain.tx.sender);
|
|
336
|
-
if (this._totalSupply.value < value) throw new Revert(
|
|
309
|
+
if (this._totalSupply.value < value) throw new Revert('Insufficient supply');
|
|
337
310
|
if (!this.balanceOfMap.has(Blockchain.tx.sender)) throw new Revert('No balance');
|
|
338
311
|
|
|
339
312
|
const balance: u256 = this.balanceOfMap.get(Blockchain.tx.sender);
|
|
340
|
-
if (balance < value) throw new Revert(
|
|
313
|
+
if (balance < value) throw new Revert('Insufficient balance');
|
|
341
314
|
|
|
342
315
|
const newBalance: u256 = SafeMath.sub(balance, value);
|
|
343
316
|
this.balanceOfMap.set(Blockchain.tx.sender, newBalance);
|
|
344
317
|
|
|
345
|
-
// @ts-expect-error
|
|
318
|
+
// @ts-expect-error AssemblyScript valid
|
|
346
319
|
this._totalSupply -= value;
|
|
347
320
|
|
|
348
321
|
this.createBurnEvent(value);
|
|
@@ -355,12 +328,11 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
355
328
|
if (!this.balanceOfMap.has(to)) {
|
|
356
329
|
this.balanceOfMap.set(to, value);
|
|
357
330
|
} else {
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
this.balanceOfMap.set(to, newToBalance);
|
|
331
|
+
const toBal: u256 = this.balanceOfMap.get(to);
|
|
332
|
+
this.balanceOfMap.set(to, SafeMath.add(toBal, value));
|
|
361
333
|
}
|
|
362
334
|
|
|
363
|
-
// @ts-expect-error
|
|
335
|
+
// @ts-expect-error AssemblyScript valid
|
|
364
336
|
this._totalSupply += value;
|
|
365
337
|
|
|
366
338
|
if (this._totalSupply.value > this.maxSupply) throw new Revert('Max supply reached');
|
|
@@ -370,20 +342,16 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
370
342
|
|
|
371
343
|
protected _transfer(to: Address, value: u256): boolean {
|
|
372
344
|
const sender = Blockchain.tx.sender;
|
|
373
|
-
if (this.isSelf(sender)) throw new Revert('
|
|
374
|
-
if (u256.eq(value, u256.Zero))
|
|
375
|
-
throw new Revert(`Cannot transfer 0 tokens`);
|
|
376
|
-
}
|
|
345
|
+
if (this.isSelf(sender)) throw new Revert('Cannot transfer from self');
|
|
346
|
+
if (u256.eq(value, u256.Zero)) throw new Revert('Cannot transfer 0');
|
|
377
347
|
|
|
378
348
|
const balance: u256 = this.balanceOfMap.get(sender);
|
|
379
|
-
if (balance < value) throw new Revert(
|
|
349
|
+
if (balance < value) throw new Revert('Insufficient balance');
|
|
380
350
|
|
|
381
|
-
|
|
382
|
-
this.balanceOfMap.set(sender, newBalance);
|
|
351
|
+
this.balanceOfMap.set(sender, SafeMath.sub(balance, value));
|
|
383
352
|
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
this.balanceOfMap.set(to, newToBalance);
|
|
353
|
+
const toBal: u256 = this.balanceOfMap.get(to);
|
|
354
|
+
this.balanceOfMap.set(to, SafeMath.add(toBal, value));
|
|
387
355
|
|
|
388
356
|
this.createTransferEvent(sender, to, value);
|
|
389
357
|
return true;
|
|
@@ -393,20 +361,16 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
393
361
|
protected _unsafeTransferFrom(from: Address, to: Address, value: u256): boolean {
|
|
394
362
|
const balance: u256 = this.balanceOfMap.get(from);
|
|
395
363
|
if (balance < value) {
|
|
396
|
-
throw new Revert(
|
|
397
|
-
`TransferFrom insufficient balance of ${from.toHex()} is ${balance} and value is ${value}`,
|
|
398
|
-
);
|
|
364
|
+
throw new Revert(`TransferFrom insufficient balance`);
|
|
399
365
|
}
|
|
400
366
|
|
|
401
|
-
|
|
402
|
-
this.balanceOfMap.set(from, newBalance);
|
|
367
|
+
this.balanceOfMap.set(from, SafeMath.sub(balance, value));
|
|
403
368
|
|
|
404
369
|
if (!this.balanceOfMap.has(to)) {
|
|
405
370
|
this.balanceOfMap.set(to, value);
|
|
406
371
|
} else {
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
this.balanceOfMap.set(to, newToBalance);
|
|
372
|
+
const toBal: u256 = this.balanceOfMap.get(to);
|
|
373
|
+
this.balanceOfMap.set(to, SafeMath.add(toBal, value));
|
|
410
374
|
}
|
|
411
375
|
|
|
412
376
|
this.createTransferEvent(from, to, value);
|
|
@@ -414,49 +378,38 @@ export abstract class DeployableOP_20 extends OP_NET implements IOP_20 {
|
|
|
414
378
|
}
|
|
415
379
|
|
|
416
380
|
protected _transferFrom(from: Address, to: Address, value: u256): boolean {
|
|
417
|
-
if (from === Blockchain.DEAD_ADDRESS)
|
|
418
|
-
throw new Revert('Cannot transfer to or from dead address');
|
|
419
|
-
}
|
|
381
|
+
if (from === Blockchain.DEAD_ADDRESS) throw new Revert('Cannot transfer from dead address');
|
|
420
382
|
|
|
421
383
|
this._spendAllowance(from, Blockchain.tx.sender, value);
|
|
422
384
|
this._unsafeTransferFrom(from, to, value);
|
|
423
|
-
|
|
424
385
|
return true;
|
|
425
386
|
}
|
|
426
387
|
|
|
427
388
|
protected _spendAllowance(owner: Address, spender: Address, value: u256): void {
|
|
428
|
-
const
|
|
429
|
-
const allowed: u256 =
|
|
389
|
+
const ownerMap = this.allowanceMap.get(owner);
|
|
390
|
+
const allowed: u256 = ownerMap.get(spender);
|
|
430
391
|
|
|
431
392
|
if (allowed < value) {
|
|
432
|
-
throw new Revert(
|
|
433
|
-
`Insufficient allowance ${allowed} < ${value}. Spender: ${spender} - Owner: ${owner}`,
|
|
434
|
-
);
|
|
393
|
+
throw new Revert('Insufficient allowance');
|
|
435
394
|
}
|
|
436
395
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this.allowanceMap.set(owner, ownerAllowanceMap);
|
|
396
|
+
ownerMap.set(spender, SafeMath.sub(allowed, value));
|
|
397
|
+
this.allowanceMap.set(owner, ownerMap);
|
|
441
398
|
}
|
|
442
399
|
|
|
443
400
|
protected createBurnEvent(value: u256): void {
|
|
444
|
-
|
|
445
|
-
this.emitEvent(burnEvent);
|
|
401
|
+
this.emitEvent(new BurnEvent(value));
|
|
446
402
|
}
|
|
447
403
|
|
|
448
404
|
protected createApproveEvent(owner: Address, spender: Address, value: u256): void {
|
|
449
|
-
|
|
450
|
-
this.emitEvent(approveEvent);
|
|
405
|
+
this.emitEvent(new ApproveEvent(owner, spender, value));
|
|
451
406
|
}
|
|
452
407
|
|
|
453
408
|
protected createMintEvent(recipient: Address, value: u256): void {
|
|
454
|
-
|
|
455
|
-
this.emitEvent(mintEvent);
|
|
409
|
+
this.emitEvent(new MintEvent(recipient, value));
|
|
456
410
|
}
|
|
457
411
|
|
|
458
412
|
protected createTransferEvent(from: Address, to: Address, value: u256): void {
|
|
459
|
-
|
|
460
|
-
this.emitEvent(transferEvent);
|
|
413
|
+
this.emitEvent(new TransferEvent(from, to, value));
|
|
461
414
|
}
|
|
462
415
|
}
|
|
@@ -200,7 +200,7 @@ export class BlockchainEnvironment {
|
|
|
200
200
|
|
|
201
201
|
public emit(event: NetEvent): void {
|
|
202
202
|
const data = event.getEventData();
|
|
203
|
-
const writer = new BytesWriter(event.eventType.length +
|
|
203
|
+
const writer = new BytesWriter(event.eventType.length + 8 + data.byteLength);
|
|
204
204
|
|
|
205
205
|
writer.writeStringWithLength(event.eventType);
|
|
206
206
|
writer.writeBytesWithLength(data);
|