@btc-vision/btc-runtime 1.10.12 → 1.11.0-alpha

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.
@@ -0,0 +1,396 @@
1
+ # Upgradeable
2
+
3
+ The `Upgradeable` base class provides a secure upgrade mechanism with configurable timelock protection. Contracts extending `Upgradeable` can replace their bytecode while giving users time to assess pending changes.
4
+
5
+ > **Alternative**: If you're already extending another base class (like `OP20` or `OP721`), use the [`UpgradeablePlugin`](../advanced/contract-upgrades.md#using-the-upgradeableplugin) instead. Just call `this.registerPlugin(new UpgradeablePlugin(144))` in your constructor - no other code changes needed!
6
+
7
+ ## Overview
8
+
9
+ ```typescript
10
+ import {
11
+ Upgradeable,
12
+ Calldata,
13
+ BytesWriter,
14
+ encodeSelector,
15
+ Selector,
16
+ ADDRESS_BYTE_LENGTH,
17
+ } from '@btc-vision/btc-runtime/runtime';
18
+
19
+ @final
20
+ export class MyContract extends Upgradeable {
21
+ // Set delay: 144 blocks = ~24 hours
22
+ protected readonly upgradeDelay: u64 = 144;
23
+
24
+ public override execute(method: Selector, calldata: Calldata): BytesWriter {
25
+ switch (method) {
26
+ case encodeSelector('submitUpgrade'):
27
+ return this.submitUpgrade(calldata.readAddress());
28
+ case encodeSelector('applyUpgrade'): {
29
+ const sourceAddress = calldata.readAddress();
30
+ const remainingLength = calldata.byteLength - ADDRESS_BYTE_LENGTH;
31
+ const updateCalldata = new BytesWriter(remainingLength);
32
+ if (remainingLength > 0) {
33
+ updateCalldata.writeBytes(calldata.readBytes(remainingLength));
34
+ }
35
+ return this.applyUpgrade(sourceAddress, updateCalldata);
36
+ }
37
+ case encodeSelector('cancelUpgrade'):
38
+ return this.cancelUpgrade();
39
+ default:
40
+ return super.execute(method, calldata);
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Class Reference
47
+
48
+ ### Properties
49
+
50
+ | Property | Type | Description |
51
+ |----------|------|-------------|
52
+ | `upgradeDelay` | `u64` | Blocks to wait before upgrade can be applied (default: 144 = ~24h) |
53
+ | `pendingUpgradeAddress` | `Address` | Source address of pending upgrade (zero if none) |
54
+ | `pendingUpgradeBlock` | `u64` | Block when upgrade was submitted (0 if none) |
55
+ | `upgradeEffectiveBlock` | `u64` | Block when upgrade can be applied (0 if none) |
56
+ | `hasPendingUpgrade` | `bool` | Whether an upgrade is pending |
57
+ | `canApplyUpgrade` | `bool` | Whether the delay has elapsed |
58
+
59
+ ### Methods
60
+
61
+ #### submitUpgrade
62
+
63
+ Submits an upgrade for timelock. Only callable by deployer.
64
+
65
+ ```typescript
66
+ protected submitUpgrade(sourceAddress: Address): BytesWriter
67
+ ```
68
+
69
+ **Parameters:**
70
+ - `sourceAddress`: The address of the contract containing the new bytecode
71
+
72
+ **Reverts if:**
73
+ - Caller is not the deployer
74
+ - Source is not a deployed contract
75
+ - An upgrade is already pending
76
+
77
+ **Emits:** `UpgradeSubmitted(sourceAddress, submitBlock, effectiveBlock)`
78
+
79
+ #### applyUpgrade
80
+
81
+ Applies a pending upgrade after the delay has passed. Only callable by deployer.
82
+
83
+ ```typescript
84
+ protected applyUpgrade(sourceAddress: Address, calldata: BytesWriter): BytesWriter
85
+ ```
86
+
87
+ **Parameters:**
88
+ - `sourceAddress`: The source contract address (must match pending)
89
+ - `calldata`: Data passed to the `onUpdate` hook of the new contract
90
+
91
+ **Reverts if:**
92
+ - Caller is not the deployer
93
+ - No upgrade is pending
94
+ - Delay has not elapsed
95
+ - Address does not match pending upgrade
96
+
97
+ **Emits:** `UpgradeApplied(sourceAddress, appliedAtBlock)`
98
+
99
+ #### cancelUpgrade
100
+
101
+ Cancels a pending upgrade. Only callable by deployer.
102
+
103
+ ```typescript
104
+ protected cancelUpgrade(): BytesWriter
105
+ ```
106
+
107
+ **Reverts if:**
108
+ - Caller is not the deployer
109
+ - No upgrade is pending
110
+
111
+ **Emits:** `UpgradeCancelled(sourceAddress, cancelledAtBlock)`
112
+
113
+ ## Events
114
+
115
+ ### UpgradeSubmittedEvent
116
+
117
+ Emitted when an upgrade is submitted.
118
+
119
+ ```typescript
120
+ class UpgradeSubmittedEvent extends NetEvent {
121
+ constructor(
122
+ sourceAddress: Address, // Contract with new bytecode
123
+ submitBlock: u64, // Block when submitted
124
+ effectiveBlock: u64 // Block when can be applied
125
+ )
126
+ }
127
+ ```
128
+
129
+ ### UpgradeAppliedEvent
130
+
131
+ Emitted when an upgrade is applied.
132
+
133
+ ```typescript
134
+ class UpgradeAppliedEvent extends NetEvent {
135
+ constructor(
136
+ sourceAddress: Address, // Contract with new bytecode
137
+ appliedAtBlock: u64 // Block when applied
138
+ )
139
+ }
140
+ ```
141
+
142
+ ### UpgradeCancelledEvent
143
+
144
+ Emitted when a pending upgrade is cancelled.
145
+
146
+ ```typescript
147
+ class UpgradeCancelledEvent extends NetEvent {
148
+ constructor(
149
+ sourceAddress: Address, // Cancelled source contract
150
+ cancelledAtBlock: u64 // Block when cancelled
151
+ )
152
+ }
153
+ ```
154
+
155
+ ## Usage Patterns
156
+
157
+ ### Basic Upgradeable Contract
158
+
159
+ ```typescript
160
+ @final
161
+ export class SimpleUpgradeable extends Upgradeable {
162
+ protected readonly upgradeDelay: u64 = 144; // ~1 day
163
+
164
+ public override execute(method: Selector, calldata: Calldata): BytesWriter {
165
+ switch (method) {
166
+ case encodeSelector('submitUpgrade'):
167
+ return this.submitUpgrade(calldata.readAddress());
168
+ case encodeSelector('applyUpgrade'): {
169
+ const sourceAddress = calldata.readAddress();
170
+ const remainingLength = calldata.byteLength - ADDRESS_BYTE_LENGTH;
171
+ const updateCalldata = new BytesWriter(remainingLength);
172
+ if (remainingLength > 0) {
173
+ updateCalldata.writeBytes(calldata.readBytes(remainingLength));
174
+ }
175
+ return this.applyUpgrade(sourceAddress, updateCalldata);
176
+ }
177
+ case encodeSelector('cancelUpgrade'):
178
+ return this.cancelUpgrade();
179
+ default:
180
+ return super.execute(method, calldata);
181
+ }
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### With Upgrade Status Views
187
+
188
+ ```typescript
189
+ @final
190
+ export class UpgradeableWithViews extends Upgradeable {
191
+ protected readonly upgradeDelay: u64 = 1008; // ~1 week
192
+
193
+ public override execute(method: Selector, calldata: Calldata): BytesWriter {
194
+ switch (method) {
195
+ // Upgrade actions
196
+ case encodeSelector('submitUpgrade'):
197
+ return this.submitUpgrade(calldata.readAddress());
198
+ case encodeSelector('applyUpgrade'): {
199
+ const sourceAddress = calldata.readAddress();
200
+ const remainingLength = calldata.byteLength - ADDRESS_BYTE_LENGTH;
201
+ const updateCalldata = new BytesWriter(remainingLength);
202
+ if (remainingLength > 0) {
203
+ updateCalldata.writeBytes(calldata.readBytes(remainingLength));
204
+ }
205
+ return this.applyUpgrade(sourceAddress, updateCalldata);
206
+ }
207
+ case encodeSelector('cancelUpgrade'):
208
+ return this.cancelUpgrade();
209
+
210
+ // View methods
211
+ case encodeSelector('getPendingUpgrade'):
212
+ return this.getPendingUpgrade();
213
+ case encodeSelector('getUpgradeStatus'):
214
+ return this.getUpgradeStatus();
215
+
216
+ default:
217
+ return super.execute(method, calldata);
218
+ }
219
+ }
220
+
221
+ private getPendingUpgrade(): BytesWriter {
222
+ const response = new BytesWriter(32);
223
+ response.writeAddress(this.pendingUpgradeAddress);
224
+ return response;
225
+ }
226
+
227
+ private getUpgradeStatus(): BytesWriter {
228
+ const response = new BytesWriter(17);
229
+ response.writeBoolean(this.hasPendingUpgrade);
230
+ response.writeU64(this.pendingUpgradeBlock);
231
+ response.writeU64(this.upgradeEffectiveBlock);
232
+ return response;
233
+ }
234
+ }
235
+ ```
236
+
237
+ ### Emergency Upgrades (Not Recommended)
238
+
239
+ For contracts that need faster upgrades (use with caution):
240
+
241
+ ```typescript
242
+ @final
243
+ export class QuickUpgradeable extends Upgradeable {
244
+ // Only 6 blocks (~1 hour) - use only for emergencies
245
+ protected readonly upgradeDelay: u64 = 6;
246
+
247
+ // ... rest of implementation
248
+ }
249
+ ```
250
+
251
+ ## Security Considerations
252
+
253
+ ### 1. Delay Selection
254
+
255
+ Choose an appropriate delay based on your contract's risk profile:
256
+
257
+ | Contract Type | Recommended Delay |
258
+ |---------------|-------------------|
259
+ | Test/Development | 1-6 blocks |
260
+ | Standard DeFi | 144 blocks (~24 hours) |
261
+ | High-value vaults | 1008 blocks (~1 week) |
262
+ | Governance contracts | 4320 blocks (~1 month) |
263
+
264
+ ### 2. Source Validation
265
+
266
+ The `submitUpgrade` function validates that the source is a deployed contract. This prevents:
267
+ - Submitting non-existent addresses
268
+ - Last-minute malicious deployments
269
+
270
+ ### 3. Address Match Verification
271
+
272
+ The `applyUpgrade` function requires the address to match the pending upgrade. This prevents:
273
+ - Front-running attacks
274
+ - Address substitution attacks
275
+
276
+ ### 4. Storage Compatibility
277
+
278
+ When upgrading, ensure storage layout compatibility:
279
+
280
+ ```typescript
281
+ // V1 - Original
282
+ class ContractV1 extends Upgradeable {
283
+ private ptr1: u16 = Blockchain.nextPointer; // Pointer 1
284
+ private ptr2: u16 = Blockchain.nextPointer; // Pointer 2
285
+ }
286
+
287
+ // V2 - Add new pointers at the END
288
+ class ContractV2 extends Upgradeable {
289
+ private ptr1: u16 = Blockchain.nextPointer; // Pointer 1 (same)
290
+ private ptr2: u16 = Blockchain.nextPointer; // Pointer 2 (same)
291
+ private ptr3: u16 = Blockchain.nextPointer; // Pointer 3 (NEW)
292
+ }
293
+ ```
294
+
295
+ ## Upgrade Workflow
296
+
297
+ ```
298
+ 1. Deploy new bytecode contract
299
+ └─> Returns: newContractAddress
300
+
301
+ 2. Submit upgrade
302
+ └─> submitUpgrade(newContractAddress)
303
+ └─> Emits: UpgradeSubmitted
304
+
305
+ 3. Wait for delay
306
+ └─> Users can monitor and exit
307
+
308
+ 4. Apply upgrade
309
+ └─> applyUpgrade(newContractAddress)
310
+ └─> Emits: UpgradeApplied
311
+ └─> VM calls onUpdate() on new bytecode
312
+ └─> New bytecode active next block
313
+
314
+ 5. (Optional) Discard source contract
315
+ └─> Source contract can be abandoned
316
+ ```
317
+
318
+ ### The onUpdate Hook
319
+
320
+ Override `onUpdate` in your new contract version to perform migrations:
321
+
322
+ ```typescript
323
+ @final
324
+ export class MyContractV2 extends Upgradeable {
325
+ protected readonly upgradeDelay: u64 = 144;
326
+
327
+ // New storage added in V2
328
+ private newFeaturePointer: u16 = Blockchain.nextPointer;
329
+ private _newFeature: StoredU256;
330
+
331
+ public constructor() {
332
+ super();
333
+ this._newFeature = new StoredU256(this.newFeaturePointer, EMPTY_POINTER);
334
+ }
335
+
336
+ public override onUpdate(calldata: Calldata): void {
337
+ super.onUpdate(calldata);
338
+ // Initialize new storage
339
+ this._newFeature.value = u256.fromU64(100);
340
+ }
341
+
342
+ // ... execute() and other methods
343
+ }
344
+ ```
345
+
346
+ See [The onUpdate Lifecycle Hook](../advanced/contract-upgrades.md#the-onupdate-lifecycle-hook) for more details.
347
+
348
+ ## Combining with Other Base Classes
349
+
350
+ ### Upgradeable + ReentrancyGuard
351
+
352
+ ```typescript
353
+ // Create a combined base class
354
+ class UpgradeableWithReentrancy extends Upgradeable {
355
+ protected readonly reentrancyLevel: ReentrancyLevel = ReentrancyLevel.STANDARD;
356
+ private _locked: StoredBoolean;
357
+
358
+ protected constructor() {
359
+ super();
360
+ this._locked = new StoredBoolean(Blockchain.nextPointer, false);
361
+ }
362
+
363
+ protected nonReentrant(): void {
364
+ if (this._locked.value) {
365
+ throw new Revert('ReentrancyGuard: LOCKED');
366
+ }
367
+ this._locked.value = true;
368
+ }
369
+
370
+ protected releaseGuard(): void {
371
+ this._locked.value = false;
372
+ }
373
+ }
374
+
375
+ @final
376
+ export class SecureUpgradeableVault extends UpgradeableWithReentrancy {
377
+ // Implementation with both upgrade and reentrancy protection
378
+ }
379
+ ```
380
+
381
+ ## Solidity Comparison
382
+
383
+ | Feature | OpenZeppelin UUPS | OPNet Upgradeable |
384
+ |---------|-------------------|-------------------|
385
+ | Upgrade mechanism | delegatecall | Native bytecode replacement |
386
+ | Storage location | Implementation contract | Same contract |
387
+ | Proxy overhead | Yes | No |
388
+ | Timelock | Separate contract (optional) | Built-in |
389
+ | Events | Custom | Built-in |
390
+ | Cancel upgrade | Custom implementation | Built-in |
391
+
392
+ ---
393
+
394
+ **Navigation:**
395
+ - Previous: [ReentrancyGuard](./reentrancy-guard.md)
396
+ - Next: [Address Type](../types/address.md)
@@ -587,7 +587,6 @@ classDiagram
587
587
  +getBlockHash(blockNumber) Uint8Array
588
588
  +emit(event) void
589
589
  +log(data) void
590
- +registerPlugin(plugin) void
591
590
  }
592
591
 
593
592
  class Block {
@@ -715,7 +714,6 @@ export class MyContract extends OP_NET {
715
714
  | `Blockchain.getBlockHash()` | `Uint8Array` | Historical block hash |
716
715
  | `Blockchain.emit()` | `void` | Emit event |
717
716
  | `Blockchain.log()` | `void` | Debug logging (testing only) |
718
- | `Blockchain.registerPlugin()` | `void` | Register a plugin |
719
717
 
720
718
  ---
721
719
 
@@ -31,6 +31,7 @@ classDiagram
31
31
  -Uint8Array typedArray
32
32
  -u32 currentOffset
33
33
  +BytesWriter(length)
34
+ +write~T~(value) void
34
35
  +writeU8(value)
35
36
  +writeU16(value, be)
36
37
  +writeU32(value, be)
@@ -38,9 +39,13 @@ classDiagram
38
39
  +writeU128(value, be)
39
40
  +writeU256(value, be)
40
41
  +writeAddress(addr)
42
+ +writeExtendedAddress(extAddr)
43
+ +writeSchnorrSignature(addr, sig)
41
44
  +writeString(str)
42
45
  +writeBytes(data)
43
46
  +writeBoolean(bool)
47
+ +writeExtendedAddressArray(arr)
48
+ +writeExtendedAddressMapU256(map)
44
49
  +getBuffer() Uint8Array
45
50
  }
46
51
 
@@ -48,6 +53,7 @@ classDiagram
48
53
  -DataView buffer
49
54
  -i32 currentOffset
50
55
  +BytesReader(bytes)
56
+ +read~T~() T
51
57
  +readU8() u8
52
58
  +readU16(be) u16
53
59
  +readU32(be) u32
@@ -55,9 +61,13 @@ classDiagram
55
61
  +readU128(be) u128
56
62
  +readU256(be) u256
57
63
  +readAddress() Address
64
+ +readExtendedAddress() ExtendedAddress
65
+ +readSchnorrSignature() SchnorrSignature
58
66
  +readString() string
59
67
  +readBytes(length) Uint8Array
60
68
  +readBoolean() bool
69
+ +readExtendedAddressArray() ExtendedAddress[]
70
+ +readExtendedAddressMapU256() ExtendedAddressMap
61
71
  +hasMoreData() bool
62
72
  }
63
73
 
@@ -113,6 +123,12 @@ writer.writeI64(value);
113
123
  // Address (32 bytes)
114
124
  writer.writeAddress(address);
115
125
 
126
+ // ExtendedAddress (64 bytes: 32 tweaked key + 32 ML-DSA key hash)
127
+ writer.writeExtendedAddress(extendedAddress);
128
+
129
+ // Schnorr signature with signer address (128 bytes total)
130
+ writer.writeSchnorrSignature(signerAddress, signature);
131
+
116
132
  // String without length prefix
117
133
  writer.writeString('Hello, World!');
118
134
 
@@ -129,6 +145,25 @@ writer.writeBytesWithLength(data);
129
145
  writer.writeSelector(selector);
130
146
  ```
131
147
 
148
+ ### Generic Write Method
149
+
150
+ The `write<T>()` method automatically selects the correct write method based on the type:
151
+
152
+ ```typescript
153
+ // Automatically dispatches to the correct write method
154
+ writer.write<u64>(12345); // writeU64
155
+ writer.write<u256>(amount); // writeU256
156
+ writer.write<bool>(true); // writeBoolean
157
+ writer.write<Address>(addr); // writeAddress
158
+ writer.write<ExtendedAddress>(extAddr); // writeExtendedAddress
159
+ writer.write<string>('hello'); // writeStringWithLength
160
+
161
+ // Supported types:
162
+ // - Primitives: bool, u8, u16, u32, u64, i8, i16, i32, i64
163
+ // - Big numbers: u128, u256, i128
164
+ // - Complex: Address, ExtendedAddress, Selector, string, Uint8Array
165
+ ```
166
+
132
167
  ### Writing Arrays
133
168
 
134
169
  All array methods use a u16 length prefix (max 65535 elements):
@@ -137,6 +172,9 @@ All array methods use a u16 length prefix (max 65535 elements):
137
172
  // Address array (u16 length prefix + addresses)
138
173
  writer.writeAddressArray(addresses);
139
174
 
175
+ // ExtendedAddress array (u16 length prefix + 64-byte addresses)
176
+ writer.writeExtendedAddressArray(extendedAddresses);
177
+
140
178
  // Numeric arrays (u16 length prefix + values)
141
179
  writer.writeU8Array(u8Values);
142
180
  writer.writeU16Array(u16Values);
@@ -150,6 +188,9 @@ writer.writeArrayOfBuffer(buffers);
150
188
 
151
189
  // AddressMap<u256> (u16 count, then address + u256 pairs)
152
190
  writer.writeAddressMapU256(addressMap);
191
+
192
+ // ExtendedAddressMap<u256> (u16 count, then 64-byte address + u256 pairs)
193
+ writer.writeExtendedAddressMapU256(extendedAddressMap);
153
194
  ```
154
195
 
155
196
  ### Getting Results
@@ -222,6 +263,14 @@ const i64val: i64 = reader.readI64();
222
263
  // Address (32 bytes)
223
264
  const addr: Address = reader.readAddress();
224
265
 
266
+ // ExtendedAddress (64 bytes: 32 tweaked key + 32 ML-DSA key hash)
267
+ const extAddr: ExtendedAddress = reader.readExtendedAddress();
268
+
269
+ // Schnorr signature with signer address (128 bytes)
270
+ const schnorrSig: SchnorrSignature = reader.readSchnorrSignature();
271
+ const signer: ExtendedAddress = schnorrSig.address;
272
+ const signature: Uint8Array = schnorrSig.signature;
273
+
225
274
  // String with known length (bytes read, zeroStop = true)
226
275
  const name: string = reader.readString(32); // reads up to 32 bytes, stops at null
227
276
 
@@ -238,6 +287,25 @@ const data2: Uint8Array = reader.readBytesWithLength();
238
287
  const selector: Selector = reader.readSelector();
239
288
  ```
240
289
 
290
+ ### Generic Read Method
291
+
292
+ The `read<T>()` method automatically selects the correct read method based on the type:
293
+
294
+ ```typescript
295
+ // Automatically dispatches to the correct read method
296
+ const num: u64 = reader.read<u64>(); // readU64
297
+ const amount: u256 = reader.read<u256>(); // readU256
298
+ const flag: bool = reader.read<bool>(); // readBoolean
299
+ const addr: Address = reader.read<Address>(); // readAddress
300
+ const extAddr: ExtendedAddress = reader.read<ExtendedAddress>(); // readExtendedAddress
301
+ const text: string = reader.read<string>(); // readStringWithLength
302
+
303
+ // Supported types:
304
+ // - Primitives: bool, u8, u16, u32, u64, i8, i16, i32, i64
305
+ // - Big numbers: u128, u256, i128
306
+ // - Complex: Address, ExtendedAddress, Selector, string
307
+ ```
308
+
241
309
  ### Reading Arrays
242
310
 
243
311
  All array methods expect a u16 length prefix:
@@ -246,6 +314,9 @@ All array methods expect a u16 length prefix:
246
314
  // Address array
247
315
  const addresses: Address[] = reader.readAddressArray();
248
316
 
317
+ // ExtendedAddress array (64 bytes each)
318
+ const extAddresses: ExtendedAddress[] = reader.readExtendedAddressArray();
319
+
249
320
  // Numeric arrays
250
321
  const u8Values: u8[] = reader.readU8Array();
251
322
  const u16Values: u16[] = reader.readU16Array();
@@ -259,6 +330,9 @@ const buffers: Uint8Array[] = reader.readArrayOfBuffer();
259
330
 
260
331
  // AddressMap<u256>
261
332
  const addressMap: AddressMap<u256> = reader.readAddressMapU256();
333
+
334
+ // ExtendedAddressMap<u256> (64-byte addresses as keys)
335
+ const extAddressMap: ExtendedAddressMap<u256> = reader.readExtendedAddressMapU256();
262
336
  ```
263
337
 
264
338
  ### Position Management
@@ -291,6 +365,8 @@ reader.verifyEnd(offset + 32); // Throws Revert if not enough bytes
291
365
  | `u128`/`i128` | 16 | Big-endian (default) |
292
366
  | `u256` | 32 | Big-endian (default) |
293
367
  | `Address` | 32 | Raw bytes |
368
+ | `ExtendedAddress` | 64 | 32 bytes tweaked key + 32 bytes ML-DSA key hash |
369
+ | `SchnorrSignature` | 128 | 64 bytes ExtendedAddress + 64 bytes signature |
294
370
  | `Selector` | 4 | Big-endian (u32) |
295
371
  | `string` | 4 + n | Length prefix (u32 BE) + UTF-8 |
296
372
  | `bytes` | 4 + n | Length prefix (u32 BE) + raw |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/btc-runtime",
3
- "version": "1.10.12",
3
+ "version": "1.11.0-alpha",
4
4
  "description": "Bitcoin L1 Smart Contract Runtime for OPNet. Build decentralized applications on Bitcoin using AssemblyScript and WebAssembly. Fully audited.",
5
5
  "main": "btc/index.ts",
6
6
  "types": "btc/index.ts",
@@ -56,17 +56,17 @@
56
56
  "docs"
57
57
  ],
58
58
  "engines": {
59
- "node": ">=22.0.0"
59
+ "node": ">=24.0.0"
60
60
  },
61
61
  "dependencies": {
62
62
  "@assemblyscript/loader": "^0.28.9",
63
63
  "@btc-vision/as-bignum": "^0.0.7",
64
64
  "@btc-vision/opnet-transform": "^0.2.1",
65
- "@eslint/js": "9.39.1",
65
+ "@eslint/js": "9.39.2",
66
66
  "gulplog": "^2.2.0",
67
67
  "ts-node": "^10.9.2",
68
68
  "typescript": "^5.9.3",
69
- "typescript-eslint": "^8.46.3"
69
+ "typescript-eslint": "^8.53.1"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@btc-vision/as-covers-assembly": "^0.4.4",
@@ -74,7 +74,7 @@
74
74
  "@btc-vision/as-pect-assembly": "^8.2.0",
75
75
  "@btc-vision/as-pect-cli": "^8.2.0",
76
76
  "@btc-vision/as-pect-transform": "^8.2.0",
77
- "@types/node": "^24.10.1",
77
+ "@types/node": "^25.0.9",
78
78
  "assemblyscript": "^0.28.9"
79
79
  }
80
80
  }