@btc-vision/btc-runtime 1.9.16 → 1.10.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.9.16",
3
+ "version": "1.10.0",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "scripts": {
@@ -25,7 +25,7 @@
25
25
  "@btc-vision/as-pect-assembly": "^8.2.0",
26
26
  "@btc-vision/as-pect-cli": "^8.2.0",
27
27
  "@btc-vision/as-pect-transform": "^8.2.0",
28
- "@types/node": "^24.10.0",
28
+ "@types/node": "^24.10.1",
29
29
  "assemblyscript": "^0.28.9"
30
30
  },
31
31
  "repository": {
@@ -238,7 +238,7 @@ export class BytesReader {
238
238
  public readAddress(): Address {
239
239
  this.verifyEnd(this.currentOffset + ADDRESS_BYTE_LENGTH);
240
240
 
241
- const addr = new Address();
241
+ const addr = new Address([]);
242
242
  for (let i: i32 = 0; i < ADDRESS_BYTE_LENGTH; i++) {
243
243
  addr[i] = this.readU8();
244
244
  }
@@ -79,14 +79,14 @@ export const OP721_TRANSFER_TYPE_HASH: u8[] = [
79
79
  0x64, 0xab, 0xa6, 0xaf, 0x68, 0x51, 0x03, 0xfe, 0xc4, 0xae, 0x12, 0xd7, 0xa6, 0xa9, 0xb2, 0x0f,
80
80
  ];
81
81
 
82
- export const BALANCE_OF_SELECTOR: u32 = 0x5b46f8f6; // "balanceOf(address)"
83
- export const ALLOWANCE_SELECTOR: u32 = 0xd864b7ca; // "allowance(address,address)"
84
- export const TOTAL_SUPPLY_SELECTOR: u32 = 0xa368022e; // "totalSupply()"
85
- export const NAME_SELECTOR: u32 = 0x1581f81c; // "name()"
86
- export const SYMBOL_SELECTOR: u32 = 0x25967ca5; // "symbol()"
87
- export const DECIMALS_SELECTOR: u32 = 0xbb844440; // "decimals()"
88
- export const NONCE_OF_SELECTOR: u32 = 0xf6824b65; // "nonceOf(address)"
89
- export const DOMAIN_SEPARATOR_SELECTOR:u32 = 0xf1bf80e0; // "domainSeparator()"
90
- export const METADATA_SELECTOR: u32 = 0xfc0d115c; // "metadata()"
91
- export const MAXIMUM_SUPPLY_SELECTOR: u32 = 0x7d8d5019; // "maximumSupply()"
92
- export const ICON_SELECTOR: u32 = 0xaaaa50c5; // "icon()"
82
+ export const BALANCE_OF_SELECTOR: u32 = 0x5b46f8f6; // "balanceOf(address)"
83
+ export const ALLOWANCE_SELECTOR: u32 = 0xd864b7ca; // "allowance(address,address)"
84
+ export const TOTAL_SUPPLY_SELECTOR: u32 = 0xa368022e; // "totalSupply()"
85
+ export const NAME_SELECTOR: u32 = 0x1581f81c; // "name()"
86
+ export const SYMBOL_SELECTOR: u32 = 0x25967ca5; // "symbol()"
87
+ export const DECIMALS_SELECTOR: u32 = 0xbb844440; // "decimals()"
88
+ export const NONCE_OF_SELECTOR: u32 = 0xf6824b65; // "nonceOf(address)"
89
+ export const DOMAIN_SEPARATOR_SELECTOR: u32 = 0xf1bf80e0; // "domainSeparator()"
90
+ export const METADATA_SELECTOR: u32 = 0xfc0d115c; // "metadata()"
91
+ export const MAXIMUM_SUPPLY_SELECTOR: u32 = 0x7d8d5019; // "maximumSupply()"
92
+ export const ICON_SELECTOR: u32 = 0xaaaa50c5; // "icon()"
@@ -50,25 +50,95 @@ const decimalsPointer: u16 = Blockchain.nextPointer;
50
50
  const stringPointer: u16 = Blockchain.nextPointer;
51
51
  const totalSupplyPointer: u16 = Blockchain.nextPointer;
52
52
  const allowanceMapPointer: u16 = Blockchain.nextPointer;
53
-
54
53
  const balanceOfMapPointer: u16 = Blockchain.nextPointer;
55
54
 
55
+ /**
56
+ * OP20 Token Standard Implementation for OPNet.
57
+ *
58
+ * This abstract class implements the OP20 token standard, providing a complete
59
+ * fungible token implementation with advanced features including:
60
+ * - EIP-712 style typed data signatures for gasless approvals
61
+ * - Safe transfer callbacks for receiver contracts
62
+ * - Reentrancy protection for security
63
+ * - Quantum-resistant signature support (Schnorr now, ML-DSA future)
64
+ * - Unlimited approval optimization (u256.Max)
65
+ *
66
+ * @remarks
67
+ * OP20 is OPNet's equivalent of ERC20, adapted for Bitcoin's UTXO model with
68
+ * additional security features. All storage uses persistent pointers for
69
+ * cross-transaction state management. The contract includes built-in protection
70
+ * against common attack vectors including reentrancy and integer overflow.
71
+ *
72
+ * Inheriting contracts must implement deployment verification logic and can
73
+ * extend with additional features like minting permissions, pausability, etc.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * class MyToken extends OP20 {
78
+ * constructor() {
79
+ * super();
80
+ * const params: OP20InitParameters = {
81
+ * name: "My Token",
82
+ * symbol: "MTK",
83
+ * decimals: 18,
84
+ * maxSupply: u256.fromU64(1000000000000000000000000), // 1M tokens
85
+ * icon: "https://example.com/icon.png"
86
+ * };
87
+ * this.instantiate(params);
88
+ * }
89
+ * }
90
+ * ```
91
+ */
56
92
  export abstract class OP20 extends ReentrancyGuard implements IOP20 {
93
+ /**
94
+ * Total supply of tokens currently in circulation.
95
+ * Intentionally public for inherited classes to implement custom minting/burning logic.
96
+ */
97
+ public _totalSupply: StoredU256;
98
+
99
+ /**
100
+ * Reentrancy protection level for this contract.
101
+ * Set to CALLBACK to allow single-depth callbacks for safeTransfer operations.
102
+ */
57
103
  protected readonly reentrancyLevel: ReentrancyLevel = ReentrancyLevel.CALLBACK;
58
104
 
105
+ /**
106
+ * Nested mapping of owner -> spender -> allowance amount.
107
+ * Tracks approval amounts for transferFrom operations.
108
+ */
59
109
  protected readonly allowanceMap: MapOfMap<u256>;
110
+
111
+ /**
112
+ * Mapping of address -> balance.
113
+ * Stores token balances for all holders.
114
+ */
60
115
  protected readonly balanceOfMap: AddressMemoryMap;
61
116
 
117
+ /** Maximum supply that can ever be minted. */
62
118
  protected readonly _maxSupply: StoredU256;
119
+
120
+ /** Number of decimal places for token display. */
63
121
  protected readonly _decimals: StoredU256;
122
+
123
+ /** Human-readable token name. */
64
124
  protected readonly _name: StoredString;
125
+
126
+ /** Token icon URL for display in wallets/explorers. */
65
127
  protected readonly _icon: StoredString;
128
+
129
+ /** Token ticker symbol. */
66
130
  protected readonly _symbol: StoredString;
67
- protected readonly _nonceMap: AddressMemoryMap;
68
131
 
69
- /** Intentionally public for inherited classes */
70
- public _totalSupply: StoredU256;
132
+ /**
133
+ * Mapping of address -> nonce for EIP-712 signatures.
134
+ * Prevents signature replay attacks.
135
+ */
136
+ protected readonly _nonceMap: AddressMemoryMap;
71
137
 
138
+ /**
139
+ * Initializes the OP20 token with storage pointers.
140
+ * Sets up all persistent storage mappings and variables.
141
+ */
72
142
  public constructor() {
73
143
  super();
74
144
 
@@ -84,6 +154,21 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
84
154
  this._icon = new StoredString(stringPointer, 2);
85
155
  }
86
156
 
157
+ /**
158
+ * Initializes token parameters. Can only be called once.
159
+ *
160
+ * @param params - Token initialization parameters
161
+ * @param skipDeployerVerification - If true, skips deployer check (use with caution)
162
+ *
163
+ * @throws {Revert} If already initialized
164
+ * @throws {Revert} If decimals > 32
165
+ * @throws {Revert} If caller is not deployer (unless skipped)
166
+ *
167
+ * @remarks
168
+ * This method sets immutable token parameters and should be called in the
169
+ * constructor of inheriting contracts. The maximum of 32 decimals is enforced
170
+ * to prevent precision issues with u256 arithmetic.
171
+ */
87
172
  public instantiate(
88
173
  params: OP20InitParameters,
89
174
  skipDeployerVerification: boolean = false,
@@ -99,6 +184,11 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
99
184
  this._icon.value = params.icon;
100
185
  }
101
186
 
187
+ /**
188
+ * Returns the token name.
189
+ *
190
+ * @returns Token name as string
191
+ */
102
192
  @method()
103
193
  @returns({ name: 'name', type: ABIDataTypes.STRING })
104
194
  public name(_: Calldata): BytesWriter {
@@ -107,6 +197,11 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
107
197
  return w;
108
198
  }
109
199
 
200
+ /**
201
+ * Returns the token symbol.
202
+ *
203
+ * @returns Token symbol as string
204
+ */
110
205
  @method()
111
206
  @returns({ name: 'symbol', type: ABIDataTypes.STRING })
112
207
  public symbol(_: Calldata): BytesWriter {
@@ -115,6 +210,11 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
115
210
  return w;
116
211
  }
117
212
 
213
+ /**
214
+ * Returns the token icon URL.
215
+ *
216
+ * @returns Icon URL as string
217
+ */
118
218
  @method()
119
219
  @returns({ name: 'icon', type: ABIDataTypes.STRING })
120
220
  public icon(_: Calldata): BytesWriter {
@@ -123,6 +223,11 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
123
223
  return w;
124
224
  }
125
225
 
226
+ /**
227
+ * Returns the number of decimals used for display.
228
+ *
229
+ * @returns Number of decimals (0-32)
230
+ */
126
231
  @method()
127
232
  @returns({ name: 'decimals', type: ABIDataTypes.UINT8 })
128
233
  public decimals(_: Calldata): BytesWriter {
@@ -131,6 +236,11 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
131
236
  return w;
132
237
  }
133
238
 
239
+ /**
240
+ * Returns the total supply of tokens in circulation.
241
+ *
242
+ * @returns Current total supply as u256
243
+ */
134
244
  @method()
135
245
  @returns({ name: 'totalSupply', type: ABIDataTypes.UINT256 })
136
246
  public totalSupply(_: Calldata): BytesWriter {
@@ -139,6 +249,11 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
139
249
  return w;
140
250
  }
141
251
 
252
+ /**
253
+ * Returns the maximum supply that can ever exist.
254
+ *
255
+ * @returns Maximum supply cap as u256
256
+ */
142
257
  @method()
143
258
  @returns({ name: 'maximumSupply', type: ABIDataTypes.UINT256 })
144
259
  public maximumSupply(_: Calldata): BytesWriter {
@@ -147,6 +262,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
147
262
  return w;
148
263
  }
149
264
 
265
+ /**
266
+ * Returns the EIP-712 domain separator for signature verification.
267
+ *
268
+ * @returns 32-byte domain separator hash
269
+ *
270
+ * @remarks
271
+ * The domain separator includes chain ID, protocol ID, and contract address
272
+ * to prevent cross-chain and cross-contract signature replay attacks.
273
+ */
150
274
  @method()
151
275
  @returns({ name: 'domainSeparator', type: ABIDataTypes.BYTES32 })
152
276
  public domainSeparator(_: Calldata): BytesWriter {
@@ -155,6 +279,12 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
155
279
  return w;
156
280
  }
157
281
 
282
+ /**
283
+ * Returns the token balance of an address.
284
+ *
285
+ * @param calldata - Contains the address to query
286
+ * @returns Balance as u256
287
+ */
158
288
  @method({ name: 'owner', type: ABIDataTypes.ADDRESS })
159
289
  @returns({ name: 'balance', type: ABIDataTypes.UINT256 })
160
290
  public balanceOf(calldata: Calldata): BytesWriter {
@@ -164,6 +294,12 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
164
294
  return w;
165
295
  }
166
296
 
297
+ /**
298
+ * Returns the current nonce for an address (for signature verification).
299
+ *
300
+ * @param calldata - Contains the address to query
301
+ * @returns Current nonce as u256
302
+ */
167
303
  @method({ name: 'owner', type: ABIDataTypes.ADDRESS })
168
304
  @returns({ name: 'nonce', type: ABIDataTypes.UINT256 })
169
305
  public nonceOf(calldata: Calldata): BytesWriter {
@@ -173,6 +309,12 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
173
309
  return w;
174
310
  }
175
311
 
312
+ /**
313
+ * Returns the amount an address is allowed to spend on behalf of another.
314
+ *
315
+ * @param calldata - Contains owner and spender addresses
316
+ * @returns Remaining allowance as u256
317
+ */
176
318
  @method(
177
319
  { name: 'owner', type: ABIDataTypes.ADDRESS },
178
320
  { name: 'spender', type: ABIDataTypes.ADDRESS },
@@ -185,6 +327,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
185
327
  return w;
186
328
  }
187
329
 
330
+ /**
331
+ * Transfers tokens from sender to recipient.
332
+ *
333
+ * @param calldata - Contains recipient address and amount
334
+ * @emits Transferred event
335
+ *
336
+ * @throws {Revert} If sender has insufficient balance
337
+ * @throws {Revert} If recipient is zero address
338
+ */
188
339
  @method(
189
340
  { name: 'to', type: ABIDataTypes.ADDRESS },
190
341
  { name: 'amount', type: ABIDataTypes.UINT256 },
@@ -195,6 +346,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
195
346
  return new BytesWriter(0);
196
347
  }
197
348
 
349
+ /**
350
+ * Transfers tokens on behalf of another address using allowance.
351
+ *
352
+ * @param calldata - Contains from address, to address, and amount
353
+ * @emits Transferred event
354
+ *
355
+ * @throws {Revert} If insufficient allowance
356
+ * @throws {Revert} If from has insufficient balance
357
+ */
198
358
  @method(
199
359
  { name: 'from', type: ABIDataTypes.ADDRESS },
200
360
  { name: 'to', type: ABIDataTypes.ADDRESS },
@@ -212,6 +372,16 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
212
372
  return new BytesWriter(0);
213
373
  }
214
374
 
375
+ /**
376
+ * Safely transfers tokens and calls onOP20Received on recipient if it's a contract.
377
+ *
378
+ * @param calldata - Contains recipient, amount, and optional data
379
+ * @emits Transferred event
380
+ *
381
+ * @throws {Revert} If recipient contract rejects the transfer
382
+ * @remarks
383
+ * Prevents tokens from being permanently locked in contracts that can't handle them.
384
+ */
215
385
  @method(
216
386
  { name: 'to', type: ABIDataTypes.ADDRESS },
217
387
  { name: 'amount', type: ABIDataTypes.UINT256 },
@@ -228,6 +398,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
228
398
  return new BytesWriter(0);
229
399
  }
230
400
 
401
+ /**
402
+ * Safely transfers tokens on behalf of another address with callback.
403
+ *
404
+ * @param calldata - Contains from, to, amount, and optional data
405
+ * @emits Transferred event
406
+ *
407
+ * @throws {Revert} If insufficient allowance or balance
408
+ * @throws {Revert} If recipient contract rejects
409
+ */
231
410
  @method(
232
411
  { name: 'from', type: ABIDataTypes.ADDRESS },
233
412
  { name: 'to', type: ABIDataTypes.ADDRESS },
@@ -247,6 +426,16 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
247
426
  return new BytesWriter(0);
248
427
  }
249
428
 
429
+ /**
430
+ * Increases the allowance granted to a spender.
431
+ *
432
+ * @param calldata - Contains spender address and amount to increase
433
+ * @emits Approved event
434
+ *
435
+ * @remarks
436
+ * Preferred over setting allowance directly to avoid race conditions.
437
+ * If overflow would occur, sets to u256.Max (unlimited).
438
+ */
250
439
  @method(
251
440
  { name: 'spender', type: ABIDataTypes.ADDRESS },
252
441
  { name: 'amount', type: ABIDataTypes.UINT256 },
@@ -261,6 +450,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
261
450
  return new BytesWriter(0);
262
451
  }
263
452
 
453
+ /**
454
+ * Decreases the allowance granted to a spender.
455
+ *
456
+ * @param calldata - Contains spender address and amount to decrease
457
+ * @emits Approved event
458
+ *
459
+ * @remarks
460
+ * If decrease would cause underflow, sets allowance to zero.
461
+ */
264
462
  @method(
265
463
  { name: 'spender', type: ABIDataTypes.ADDRESS },
266
464
  { name: 'amount', type: ABIDataTypes.UINT256 },
@@ -275,6 +473,18 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
275
473
  return new BytesWriter(0);
276
474
  }
277
475
 
476
+ /**
477
+ * Increases allowance using an EIP-712 typed signature (gasless approval).
478
+ *
479
+ * @param calldata - Contains owner, spender, amount, deadline, and signature
480
+ * @emits Approved event
481
+ *
482
+ * @throws {Revert} If signature is invalid or expired
483
+ *
484
+ * @remarks
485
+ * Enables gasless approvals where a third party can submit the transaction.
486
+ * Uses Schnorr signatures now, will support ML-DSA after quantum transition.
487
+ */
278
488
  @method(
279
489
  { name: 'owner', type: ABIDataTypes.ADDRESS },
280
490
  { name: 'spender', type: ABIDataTypes.ADDRESS },
@@ -294,6 +504,14 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
294
504
  return new BytesWriter(0);
295
505
  }
296
506
 
507
+ /**
508
+ * Decreases allowance using an EIP-712 typed signature.
509
+ *
510
+ * @param calldata - Contains owner, spender, amount, deadline, and signature
511
+ * @emits Approved event
512
+ *
513
+ * @throws {Revert} If signature is invalid or expired
514
+ */
297
515
  @method(
298
516
  { name: 'owner', type: ABIDataTypes.ADDRESS },
299
517
  { name: 'spender', type: ABIDataTypes.ADDRESS },
@@ -313,6 +531,17 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
313
531
  return new BytesWriter(0);
314
532
  }
315
533
 
534
+ /**
535
+ * Burns tokens from the sender's balance.
536
+ *
537
+ * @param calldata - Contains amount to burn
538
+ * @emits Burned event
539
+ *
540
+ * @throws {Revert} If sender has insufficient balance
541
+ *
542
+ * @remarks
543
+ * Permanently removes tokens from circulation, decreasing total supply.
544
+ */
316
545
  @method({ name: 'amount', type: ABIDataTypes.UINT256 })
317
546
  @emit('Burned')
318
547
  public burn(calldata: Calldata): BytesWriter {
@@ -320,6 +549,14 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
320
549
  return new BytesWriter(0);
321
550
  }
322
551
 
552
+ /**
553
+ * Returns all token metadata in a single call.
554
+ *
555
+ * @returns Combined metadata including name, symbol, icon, decimals, totalSupply, and domain separator
556
+ *
557
+ * @remarks
558
+ * Optimization for wallets/explorers to fetch all token info in one call.
559
+ */
323
560
  @method()
324
561
  @returns(
325
562
  { name: 'name', type: ABIDataTypes.STRING },
@@ -359,22 +596,34 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
359
596
  return w;
360
597
  }
361
598
 
599
+ /**
600
+ * Internal: Gets balance of an address.
601
+ * @protected
602
+ */
362
603
  protected _balanceOf(owner: Address): u256 {
363
604
  if (!this.balanceOfMap.has(owner)) return u256.Zero;
364
605
  return this.balanceOfMap.get(owner);
365
606
  }
366
607
 
608
+ /**
609
+ * Internal: Gets allowance between owner and spender.
610
+ * @protected
611
+ */
367
612
  protected _allowance(owner: Address, spender: Address): u256 {
368
613
  const senderMap = this.allowanceMap.get(owner);
369
614
  return senderMap.get(spender);
370
615
  }
371
616
 
617
+ /**
618
+ * Internal: Executes token transfer logic.
619
+ * @protected
620
+ */
372
621
  protected _transfer(from: Address, to: Address, amount: u256): void {
373
- if (from === Address.zero() || from === Address.dead()) {
622
+ if (from === Address.zero()) {
374
623
  throw new Revert('Invalid sender');
375
624
  }
376
625
 
377
- if (to === Address.zero() || to === Address.dead()) {
626
+ if (to === Address.zero()) {
378
627
  throw new Revert('Invalid receiver');
379
628
  }
380
629
 
@@ -391,6 +640,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
391
640
  this.createTransferredEvent(Blockchain.tx.sender, from, to, amount);
392
641
  }
393
642
 
643
+ /**
644
+ * Internal: Safe transfer with receiver callback.
645
+ * @protected
646
+ */
394
647
  protected _safeTransfer(from: Address, to: Address, amount: u256, data: Uint8Array): void {
395
648
  this._transfer(from, to, amount);
396
649
 
@@ -401,6 +654,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
401
654
  }
402
655
  }
403
656
 
657
+ /**
658
+ * Internal: Spends allowance for transferFrom.
659
+ * @protected
660
+ */
404
661
  protected _spendAllowance(owner: Address, spender: Address, amount: u256): void {
405
662
  if (owner.equals(spender)) return;
406
663
 
@@ -417,6 +674,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
417
674
  this.allowanceMap.set(owner, ownerMap);
418
675
  }
419
676
 
677
+ /**
678
+ * Internal: Calls onOP20Received on receiver contract.
679
+ * @protected
680
+ */
420
681
  protected _callOnOP20Received(
421
682
  from: Address,
422
683
  to: Address,
@@ -448,6 +709,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
448
709
  }
449
710
  }
450
711
 
712
+ /**
713
+ * Internal: Processes signature-based allowance increase.
714
+ * @protected
715
+ */
451
716
  protected _increaseAllowanceBySignature(
452
717
  owner: Address,
453
718
  spender: Address,
@@ -466,6 +731,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
466
731
  this._increaseAllowance(owner, spender, amount);
467
732
  }
468
733
 
734
+ /**
735
+ * Checks if a selector should bypass reentrancy guards.
736
+ * @protected
737
+ */
469
738
  protected isSelectorExcluded(selector: Selector): boolean {
470
739
  if (
471
740
  selector === BALANCE_OF_SELECTOR ||
@@ -486,6 +755,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
486
755
  return super.isSelectorExcluded(selector);
487
756
  }
488
757
 
758
+ /**
759
+ * Internal: Processes signature-based allowance decrease.
760
+ * @protected
761
+ */
489
762
  protected _decreaseAllowanceBySignature(
490
763
  owner: Address,
491
764
  spender: Address,
@@ -504,6 +777,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
504
777
  this._decreaseAllowance(owner, spender, amount);
505
778
  }
506
779
 
780
+ /**
781
+ * Internal: Verifies EIP-712 typed signatures.
782
+ * @protected
783
+ */
507
784
  protected _verifySignature(
508
785
  typeHash: u8[],
509
786
  owner: Address,
@@ -547,6 +824,10 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
547
824
  this._nonceMap.set(owner, SafeMath.add(nonce, u256.One));
548
825
  }
549
826
 
827
+ /**
828
+ * Internal: Builds EIP-712 domain separator.
829
+ * @protected
830
+ */
550
831
  protected _buildDomainSeparator(): Uint8Array {
551
832
  const writer = new BytesWriter(32 * 5 + ADDRESS_BYTE_LENGTH);
552
833
  writer.writeBytesU8Array(OP712_DOMAIN_TYPE_HASH);
@@ -559,11 +840,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
559
840
  return sha256(writer.getBuffer());
560
841
  }
561
842
 
843
+ /**
844
+ * Internal: Increases allowance with overflow protection.
845
+ * @protected
846
+ */
562
847
  protected _increaseAllowance(owner: Address, spender: Address, amount: u256): void {
563
- if (owner === Address.zero() || owner === Address.dead()) {
848
+ if (owner === Address.zero()) {
564
849
  throw new Revert('Invalid approver');
565
850
  }
566
- if (spender === Address.zero() || spender === Address.dead()) {
851
+ if (spender === Address.zero()) {
567
852
  throw new Revert('Invalid spender');
568
853
  }
569
854
 
@@ -580,11 +865,15 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
580
865
  this.createApprovedEvent(owner, spender, newAllowance);
581
866
  }
582
867
 
868
+ /**
869
+ * Internal: Decreases allowance with underflow protection.
870
+ * @protected
871
+ */
583
872
  protected _decreaseAllowance(owner: Address, spender: Address, amount: u256): void {
584
- if (owner === Address.zero() || owner === Address.dead()) {
873
+ if (owner === Address.zero()) {
585
874
  throw new Revert('Invalid approver');
586
875
  }
587
- if (spender === Address.zero() || spender === Address.dead()) {
876
+ if (spender === Address.zero()) {
588
877
  throw new Revert('Invalid spender');
589
878
  }
590
879
 
@@ -602,8 +891,14 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
602
891
  this.createApprovedEvent(owner, spender, newAllowance);
603
892
  }
604
893
 
894
+ /**
895
+ * Internal: Mints new tokens to an address.
896
+ * @protected
897
+ *
898
+ * @throws {Revert} If exceeds max supply
899
+ */
605
900
  protected _mint(to: Address, amount: u256): void {
606
- if (to === Address.zero() || to === Address.dead()) {
901
+ if (to === Address.zero()) {
607
902
  throw new Revert('Invalid receiver');
608
903
  }
609
904
 
@@ -620,8 +915,12 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
620
915
  this.createMintedEvent(to, amount);
621
916
  }
622
917
 
918
+ /**
919
+ * Internal: Burns tokens from an address.
920
+ * @protected
921
+ */
623
922
  protected _burn(from: Address, amount: u256): void {
624
- if (from === Address.zero() || from === Address.dead()) {
923
+ if (from === Address.zero()) {
625
924
  throw new Revert('Invalid sender');
626
925
  }
627
926
 
@@ -635,6 +934,7 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
635
934
  this.createBurnedEvent(from, amount);
636
935
  }
637
936
 
937
+ /** Event creation helpers */
638
938
  protected createBurnedEvent(from: Address, amount: u256): void {
639
939
  this.emitEvent(new BurnedEvent(from, amount));
640
940
  }