@btc-vision/btc-runtime 1.9.13 → 1.9.15

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.13",
3
+ "version": "1.9.15",
4
4
  "description": "Bitcoin Smart Contract Runtime",
5
5
  "main": "btc/index.ts",
6
6
  "scripts": {
@@ -25,8 +25,8 @@
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.2.1",
29
- "assemblyscript": "^0.28.4"
28
+ "@types/node": "^24.10.0",
29
+ "assemblyscript": "^0.28.9"
30
30
  },
31
31
  "repository": {
32
32
  "type": "git",
@@ -43,14 +43,13 @@
43
43
  "test/*.ts"
44
44
  ],
45
45
  "dependencies": {
46
- "@assemblyscript/loader": "^0.28.4",
46
+ "@assemblyscript/loader": "^0.28.9",
47
47
  "@btc-vision/as-bignum": "^0.0.5",
48
- "@btc-vision/opnet-transform": "^0.1.11",
49
- "@eslint/js": "^9.33.0",
48
+ "@btc-vision/opnet-transform": "^0.1.12",
49
+ "@eslint/js": "9.39.1",
50
50
  "gulplog": "^2.2.0",
51
51
  "ts-node": "^10.9.2",
52
- "typescript": "^5.9.2",
53
- "typescript-eslint": "^8.39.0",
54
- "yaml": "^2.8.1"
52
+ "typescript": "^5.9.3",
53
+ "typescript-eslint": "^8.46.3"
55
54
  }
56
55
  }
@@ -66,6 +66,9 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
66
66
  protected readonly _symbol: StoredString;
67
67
  protected readonly _nonceMap: AddressMemoryMap;
68
68
 
69
+ /** Intentionally public for inherited classes */
70
+ public _totalSupply: StoredU256;
71
+
69
72
  public constructor() {
70
73
  super();
71
74
 
@@ -81,38 +84,6 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
81
84
  this._icon = new StoredString(stringPointer, 2);
82
85
  }
83
86
 
84
- /** Intentionally public for inherited classes */
85
- public _totalSupply: StoredU256;
86
-
87
- public get totalSupply(): u256 {
88
- return this._totalSupply.value;
89
- }
90
-
91
- public get name(): string {
92
- if (!this._name) throw new Revert('Name not set');
93
- return this._name.value;
94
- }
95
-
96
- public get symbol(): string {
97
- if (!this._symbol) throw new Revert('Symbol not set');
98
- return this._symbol.value;
99
- }
100
-
101
- public get icon(): string {
102
- if (!this._icon) throw new Revert('Icon not set');
103
- return this._icon.value;
104
- }
105
-
106
- public get decimals(): u8 {
107
- if (!this._decimals) throw new Revert('Decimals not set');
108
- return u8(this._decimals.value.toU32());
109
- }
110
-
111
- public get maxSupply(): u256 {
112
- if (!this._maxSupply) throw new Revert('Max supply not set');
113
- return this._maxSupply.value;
114
- }
115
-
116
87
  public instantiate(
117
88
  params: OP20InitParameters,
118
89
  skipDeployerVerification: boolean = false,
@@ -128,51 +99,51 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
128
99
  this._icon.value = params.icon;
129
100
  }
130
101
 
131
- @method('name')
102
+ @method()
132
103
  @returns({ name: 'name', type: ABIDataTypes.STRING })
133
- public fn_name(_: Calldata): BytesWriter {
134
- const w = new BytesWriter(String.UTF8.byteLength(this.name) + 4);
135
- w.writeStringWithLength(this.name);
104
+ public name(_: Calldata): BytesWriter {
105
+ const w = new BytesWriter(String.UTF8.byteLength(this._name.value) + 4);
106
+ w.writeStringWithLength(this._name.value);
136
107
  return w;
137
108
  }
138
109
 
139
- @method('symbol')
110
+ @method()
140
111
  @returns({ name: 'symbol', type: ABIDataTypes.STRING })
141
- public fn_symbol(_: Calldata): BytesWriter {
142
- const w = new BytesWriter(String.UTF8.byteLength(this.symbol) + 4);
143
- w.writeStringWithLength(this.symbol);
112
+ public symbol(_: Calldata): BytesWriter {
113
+ const w = new BytesWriter(String.UTF8.byteLength(this._symbol.value) + 4);
114
+ w.writeStringWithLength(this._symbol.value);
144
115
  return w;
145
116
  }
146
117
 
147
- @method('icon')
118
+ @method()
148
119
  @returns({ name: 'icon', type: ABIDataTypes.STRING })
149
- public fn_icon(_: Calldata): BytesWriter {
150
- const w = new BytesWriter(String.UTF8.byteLength(this.icon) + 4);
151
- w.writeStringWithLength(this.icon);
120
+ public icon(_: Calldata): BytesWriter {
121
+ const w = new BytesWriter(String.UTF8.byteLength(this._icon.value) + 4);
122
+ w.writeStringWithLength(this._icon.value);
152
123
  return w;
153
124
  }
154
125
 
155
- @method('decimals')
126
+ @method()
156
127
  @returns({ name: 'decimals', type: ABIDataTypes.UINT8 })
157
- public fn_decimals(_: Calldata): BytesWriter {
128
+ public decimals(_: Calldata): BytesWriter {
158
129
  const w = new BytesWriter(1);
159
- w.writeU8(this.decimals);
130
+ w.writeU8(this._decimals.value.toU32());
160
131
  return w;
161
132
  }
162
133
 
163
- @method('totalSupply')
134
+ @method()
164
135
  @returns({ name: 'totalSupply', type: ABIDataTypes.UINT256 })
165
- public fn_totalSupply(_: Calldata): BytesWriter {
136
+ public totalSupply(_: Calldata): BytesWriter {
166
137
  const w = new BytesWriter(U256_BYTE_LENGTH);
167
- w.writeU256(this.totalSupply);
138
+ w.writeU256(this._totalSupply.value);
168
139
  return w;
169
140
  }
170
141
 
171
- @method('maximumSupply')
142
+ @method()
172
143
  @returns({ name: 'maximumSupply', type: ABIDataTypes.UINT256 })
173
- public fn_maximumSupply(_: Calldata): BytesWriter {
144
+ public maximumSupply(_: Calldata): BytesWriter {
174
145
  const w = new BytesWriter(U256_BYTE_LENGTH);
175
- w.writeU256(this.maxSupply);
146
+ w.writeU256(this._maxSupply.value);
176
147
  return w;
177
148
  }
178
149
 
@@ -363,9 +334,9 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
363
334
  { name: 'domainSeparator', type: ABIDataTypes.BYTES32 },
364
335
  )
365
336
  public metadata(_: Calldata): BytesWriter {
366
- const name = this.name;
367
- const symbol = this.symbol;
368
- const icon = this.icon;
337
+ const name = this._name.value;
338
+ const symbol = this._symbol.value;
339
+ const icon = this._icon.value;
369
340
  const domainSeparator = this._buildDomainSeparator();
370
341
 
371
342
  const nameLength = String.UTF8.byteLength(name);
@@ -385,8 +356,8 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
385
356
  w.writeStringWithLength(name);
386
357
  w.writeStringWithLength(symbol);
387
358
  w.writeStringWithLength(icon);
388
- w.writeU8(this.decimals);
389
- w.writeU256(this.totalSupply);
359
+ w.writeU8(this._decimals.value.toU32());
360
+ w.writeU256(this._totalSupply.value);
390
361
  w.writeBytesWithLength(domainSeparator);
391
362
 
392
363
  return w;
@@ -583,7 +554,7 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
583
554
  protected _buildDomainSeparator(): Uint8Array {
584
555
  const writer = new BytesWriter(32 * 5 + ADDRESS_BYTE_LENGTH);
585
556
  writer.writeBytesU8Array(OP712_DOMAIN_TYPE_HASH);
586
- writer.writeBytes(sha256String(this.name));
557
+ writer.writeBytes(sha256String(this._name.value));
587
558
  writer.writeBytesU8Array(OP712_VERSION_HASH);
588
559
  writer.writeBytes(Blockchain.chainId);
589
560
  writer.writeBytes(Blockchain.protocolId);
@@ -646,7 +617,7 @@ export abstract class OP20 extends ReentrancyGuard implements IOP20 {
646
617
  // @ts-expect-error AssemblyScript valid
647
618
  this._totalSupply += amount;
648
619
 
649
- if (this._totalSupply.value > this.maxSupply) {
620
+ if (this._totalSupply.value > this._maxSupply.value) {
650
621
  throw new Revert('Max supply reached');
651
622
  }
652
623
 
@@ -2,12 +2,21 @@ import { BytesWriter } from '../../buffer/BytesWriter';
2
2
  import { Calldata } from '../../types';
3
3
 
4
4
  export interface IOP20 {
5
+ name(callData: Calldata): BytesWriter;
6
+ symbol(callData: Calldata): BytesWriter;
7
+ icon(callData: Calldata): BytesWriter;
8
+ decimals(callData: Calldata): BytesWriter;
9
+ totalSupply(callData: Calldata): BytesWriter;
5
10
  domainSeparator(callData: Calldata): BytesWriter;
11
+ metadata(callData: Calldata): BytesWriter;
6
12
  balanceOf(callData: Calldata): BytesWriter;
7
13
  nonceOf(callData: Calldata): BytesWriter;
8
14
  allowance(callData: Calldata): BytesWriter;
9
15
  safeTransfer(callData: Calldata): BytesWriter;
10
16
  safeTransferFrom(callData: Calldata): BytesWriter;
17
+ transfer(callData: Calldata): BytesWriter;
18
+ transferFrom(callData: Calldata): BytesWriter;
19
+ burn(callData: Calldata): BytesWriter;
11
20
  increaseAllowance(callData: Calldata): BytesWriter;
12
21
  decreaseAllowance(callData: Calldata): BytesWriter;
13
22
  increaseAllowanceBySignature(callData: Calldata): BytesWriter;
@@ -0,0 +1,6 @@
1
+ import { BytesWriter } from '../../buffer/BytesWriter';
2
+ import { Calldata } from '../../types';
3
+
4
+ export interface IOP20Receiver {
5
+ onOP20Received(callData: Calldata): BytesWriter;
6
+ }
@@ -6,11 +6,11 @@ import { NetEvent } from '../NetEvent';
6
6
 
7
7
  @final
8
8
  export class ApprovedEvent extends NetEvent {
9
- constructor(owner: Address, spender: Address, value: u256) {
9
+ constructor(owner: Address, spender: Address, amount: u256) {
10
10
  const data: BytesWriter = new BytesWriter(ADDRESS_BYTE_LENGTH * 2 + U256_BYTE_LENGTH);
11
11
  data.writeAddress(owner);
12
12
  data.writeAddress(spender);
13
- data.writeU256(value);
13
+ data.writeU256(amount);
14
14
 
15
15
  super('Approved', data);
16
16
  }
@@ -353,6 +353,7 @@ export class BitcoinCodec {
353
353
  /**
354
354
  * Validate that a witness script is within size limits
355
355
  * Bitcoin consensus rules limit witness scripts to 10,000 bytes
356
+ * Witness scripts above 3,600 bytes are non-standard and will not be relayed
356
357
  *
357
358
  * @param witnessScript - The script to validate
358
359
  * @returns true if the script is within limits
@@ -2,6 +2,7 @@ import { SegwitDecoded } from './ScriptUtils';
2
2
  import { hash160, sha256 } from '../env/global';
3
3
  import { Bech32 } from './Bech32';
4
4
  import { Revert } from '../types/Revert';
5
+ import { BitcoinCodec } from './BitcoinCodec';
5
6
 
6
7
  /**
7
8
  * Segwit provides high-level functions for creating and decoding
@@ -23,6 +24,10 @@ export class Segwit {
23
24
  * @returns The Bech32-encoded address
24
25
  */
25
26
  public static p2wsh(hrp: string, witnessScript: Uint8Array): string {
27
+ if (BitcoinCodec.isValidWitnessScriptSize(witnessScript)) {
28
+ throw new Revert('Witness script size is invalid');
29
+ }
30
+
26
31
  // P2WSH uses SHA256 of the script as the witness program
27
32
  const program = sha256(witnessScript);
28
33
  return Bech32.encode(hrp, 0, program);
@@ -33,6 +38,10 @@ export class Segwit {
33
38
  * This is useful when you need to handle encoding failures gracefully
34
39
  */
35
40
  public static p2wshOrNull(hrp: string, witnessScript: Uint8Array): string | null {
41
+ if (BitcoinCodec.isValidWitnessScriptSize(witnessScript)) {
42
+ throw new Revert('Witness script size is invalid');
43
+ }
44
+
36
45
  const program = sha256(witnessScript);
37
46
  return Bech32.encodeOrNull(hrp, 0, program);
38
47
  }
@@ -49,8 +58,8 @@ export class Segwit {
49
58
  * @returns The Bech32-encoded address
50
59
  */
51
60
  public static p2wpkh(hrp: string, pubkey: Uint8Array): string {
52
- if (pubkey.length !== 33 && pubkey.length !== 65) {
53
- throw new Revert('Public key must be 33 bytes (compressed) or 65 bytes (uncompressed)');
61
+ if (pubkey.length !== 33) {
62
+ throw new Revert('Public key must be 33 bytes');
54
63
  }
55
64
 
56
65
  // P2WPKH uses HASH160 of the public key as the witness program