@btc-vision/btc-runtime 1.11.0-rc.9 → 1.11.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.
Files changed (72) hide show
  1. package/README.md +7 -7
  2. package/docs/README.md +39 -39
  3. package/docs/advanced/bitcoin-scripts.md +17 -17
  4. package/docs/advanced/{contract-upgrades.md → contract-updates.md} +90 -98
  5. package/docs/advanced/cross-contract-calls.md +4 -4
  6. package/docs/advanced/plugins.md +21 -21
  7. package/docs/advanced/quantum-resistance.md +32 -32
  8. package/docs/advanced/signature-verification.md +22 -22
  9. package/docs/api-reference/blockchain.md +14 -14
  10. package/docs/api-reference/events.md +2 -2
  11. package/docs/api-reference/op20.md +7 -7
  12. package/docs/api-reference/op721.md +7 -7
  13. package/docs/api-reference/storage.md +2 -2
  14. package/docs/contracts/op-net-base.md +15 -15
  15. package/docs/contracts/op20-token.md +3 -3
  16. package/docs/contracts/op20s-signatures.md +2 -2
  17. package/docs/contracts/op721-nft.md +3 -3
  18. package/docs/contracts/reentrancy-guard.md +5 -7
  19. package/docs/contracts/updatable.md +384 -0
  20. package/docs/core-concepts/blockchain-environment.md +10 -10
  21. package/docs/core-concepts/decorators.md +5 -5
  22. package/docs/core-concepts/events.md +6 -6
  23. package/docs/core-concepts/pointers.md +5 -5
  24. package/docs/core-concepts/security.md +5 -5
  25. package/docs/core-concepts/storage-system.md +24 -24
  26. package/docs/examples/basic-token.md +8 -8
  27. package/docs/examples/nft-with-reservations.md +9 -9
  28. package/docs/examples/oracle-integration.md +13 -13
  29. package/docs/examples/stablecoin.md +10 -10
  30. package/docs/getting-started/first-contract.md +8 -8
  31. package/docs/getting-started/installation.md +2 -2
  32. package/docs/getting-started/project-structure.md +6 -6
  33. package/docs/storage/memory-maps.md +8 -8
  34. package/docs/storage/stored-arrays.md +6 -6
  35. package/docs/storage/stored-maps.md +8 -8
  36. package/docs/storage/stored-primitives.md +6 -6
  37. package/docs/types/address.md +13 -13
  38. package/docs/types/bytes-writer-reader.md +18 -18
  39. package/docs/types/calldata.md +12 -12
  40. package/package.json +10 -10
  41. package/runtime/constants/Exports.ts +0 -30
  42. package/runtime/contracts/OP20.ts +7 -7
  43. package/runtime/contracts/OP721.ts +60 -74
  44. package/runtime/contracts/OP_NET.ts +2 -2
  45. package/runtime/contracts/ReentrancyGuard.ts +1 -5
  46. package/runtime/contracts/Updatable.ts +241 -0
  47. package/runtime/contracts/interfaces/OP721InitParameters.ts +8 -8
  48. package/runtime/env/BlockchainEnvironment.ts +5 -5
  49. package/runtime/env/global.ts +7 -6
  50. package/runtime/events/predefined/{ApprovedEvent.ts → OP20ApprovedEvent.ts} +1 -1
  51. package/runtime/events/predefined/{BurnedEvent.ts → OP20BurnedEvent.ts} +1 -1
  52. package/runtime/events/predefined/{MintedEvent.ts → OP20MintedEvent.ts} +1 -1
  53. package/runtime/events/predefined/{TransferredEvent.ts → OP20TransferredEvent.ts} +1 -1
  54. package/runtime/events/predefined/OP721ApprovedEvent.ts +17 -0
  55. package/runtime/events/predefined/{ApprovedForAll.ts → OP721ApprovedForAllEvent.ts} +1 -1
  56. package/runtime/events/predefined/OP721BurnedEvent.ts +16 -0
  57. package/runtime/events/predefined/OP721MintedEvent.ts +16 -0
  58. package/runtime/events/predefined/OP721TransferredEvent.ts +18 -0
  59. package/runtime/events/predefined/index.ts +5 -5
  60. package/runtime/events/{upgradeable/UpgradeableEvents.ts → updatable/UpdatableEvents.ts} +9 -9
  61. package/runtime/hashing/keccak256.ts +1 -1
  62. package/runtime/index.ts +3 -5
  63. package/runtime/plugins/UpdatablePlugin.ts +276 -0
  64. package/runtime/script/Networks.ts +1 -1
  65. package/runtime/storage/StoredBoolean.ts +23 -12
  66. package/runtime/types/Address.ts +1 -1
  67. package/runtime/types/ExtendedAddress.ts +1 -1
  68. package/docs/contracts/upgradeable.md +0 -396
  69. package/runtime/contracts/Upgradeable.ts +0 -242
  70. package/runtime/contracts/interfaces/IOP1155.ts +0 -33
  71. package/runtime/contracts/interfaces/OP1155InitParameters.ts +0 -11
  72. package/runtime/plugins/UpgradeablePlugin.ts +0 -279
@@ -1,6 +1,6 @@
1
1
  # OP_NET Base Contract
2
2
 
3
- `OP_NET` is the base class for all OPNet smart contracts. It implements the `IBTC` interface and provides the foundational structure for contract lifecycle, method dispatching, event emission, and access control.
3
+ `OP_NET` is the base class for all OP_NET smart contracts. It implements the `IBTC` interface and provides the foundational structure for contract lifecycle, method dispatching, event emission, and access control.
4
4
 
5
5
  ## Overview
6
6
 
@@ -42,7 +42,7 @@ contract MyContract {
42
42
  }
43
43
  }
44
44
 
45
- // OPNet: AUTOMATIC method routing via @method decorators
45
+ // OP_NET: AUTOMATIC method routing via @method decorators
46
46
  // - Constructor runs on EVERY call
47
47
  // - Routing is automatic via decorator system
48
48
  // - One-time init in onDeployment()
@@ -52,7 +52,7 @@ contract MyContract {
52
52
 
53
53
  ### Inheritance Hierarchy
54
54
 
55
- OPNet contracts follow a clear inheritance pattern:
55
+ OP_NET contracts follow a clear inheritance pattern:
56
56
 
57
57
  ```mermaid
58
58
  classDiagram
@@ -118,7 +118,7 @@ classDiagram
118
118
 
119
119
  ### Deployment and Execution Flow
120
120
 
121
- The following diagram shows how contracts are deployed and executed on OPNet:
121
+ The following diagram shows how contracts are deployed and executed on OP_NET:
122
122
 
123
123
  ```mermaid
124
124
  ---
@@ -198,7 +198,7 @@ public constructor() {
198
198
 
199
199
  **Key Difference from Solidity:**
200
200
 
201
- | Solidity | OPNet |
201
+ | Solidity | OP_NET |
202
202
  |----------|-------|
203
203
  | Constructor runs once at deployment | Constructor runs every call |
204
204
  | Initialize state in constructor | Initialize state in `onDeployment` |
@@ -232,7 +232,7 @@ constructor(uint256 initialSupply, string memory tokenName) {
232
232
  _mint(msg.sender, initialSupply);
233
233
  }
234
234
 
235
- // OPNet: One-time init in onDeployment()
235
+ // OP_NET: One-time init in onDeployment()
236
236
  // Constructor runs every call, onDeployment runs once
237
237
  ```
238
238
 
@@ -255,7 +255,7 @@ public override onUpdate(calldata: Calldata): void {
255
255
  }
256
256
  ```
257
257
 
258
- > **Note:** This hook is called on the **new** bytecode, not the old one. See [Contract Upgrades](../advanced/contract-upgrades.md#the-onupdate-lifecycle-hook) for details.
258
+ > **Note:** This hook is called on the **new** bytecode, not the old one. See [Contract Updates](../advanced/updatable#the-onupdate-lifecycle-hook) for details.
259
259
 
260
260
  ### 3. Method Execution
261
261
 
@@ -397,12 +397,12 @@ public transfer(calldata: Calldata): BytesWriter {
397
397
  function transfer(address to, uint256 amount) public { }
398
398
  // Selector: keccak256("transfer(address,uint256)")[:4]
399
399
 
400
- // OPNet: ALSO automatic via @method decorator
400
+ // OP_NET: ALSO automatic via @method decorator
401
401
  // @method({ name: 'to', type: ABIDataTypes.ADDRESS }, ...)
402
402
  // public transfer(calldata: Calldata): BytesWriter { }
403
403
  ```
404
404
 
405
- **Note:** Both Solidity and OPNet handle selector generation automatically. In OPNet, use `@method` decorators and the runtime handles routing.
405
+ **Note:** Both Solidity and OP_NET handle selector generation automatically. In OP_NET, use `@method` decorators and the runtime handles routing.
406
406
 
407
407
  ### Built-in Methods
408
408
 
@@ -444,7 +444,7 @@ contract MyContract is Ownable {
444
444
  }
445
445
  }
446
446
 
447
- // OPNet: Built-in onlyDeployer check
447
+ // OP_NET: Built-in onlyDeployer check
448
448
  // this.onlyDeployer(Blockchain.tx.sender);
449
449
  ```
450
450
 
@@ -483,7 +483,7 @@ function setParameter(uint256 value) public onlyAdmin {
483
483
  // ...
484
484
  }
485
485
 
486
- // OPNet: Similar pattern but with explicit method call
486
+ // OP_NET: Similar pattern but with explicit method call
487
487
  // this.onlyAdmin(); at start of method
488
488
  ```
489
489
 
@@ -509,7 +509,7 @@ event Transfer(address indexed from, address indexed to, uint256 value);
509
509
 
510
510
  emit Transfer(from, to, amount);
511
511
 
512
- // OPNet: emitEvent method
512
+ // OP_NET: emitEvent method
513
513
  this.emitEvent(new TransferEvent(from, to, amount));
514
514
  ```
515
515
 
@@ -570,7 +570,7 @@ contract MyContract {
570
570
  bytes private data; // slot 2
571
571
  }
572
572
 
573
- // OPNet: Explicit pointer allocation
573
+ // OP_NET: Explicit pointer allocation
574
574
  // private counterPointer: u16 = Blockchain.nextPointer;
575
575
  // private counter: StoredU256 = new StoredU256(this.counterPointer, EMPTY_POINTER);
576
576
  ```
@@ -596,7 +596,7 @@ export class MyContract extends OP_NET {
596
596
  // Solidity: mapping declaration
597
597
  mapping(address => uint256) private balances;
598
598
 
599
- // OPNet: AddressMemoryMap with pointer
599
+ // OP_NET: AddressMemoryMap with pointer
600
600
  // private balancesPointer: u16 = Blockchain.nextPointer;
601
601
  // this.balances = new AddressMemoryMap(this.balancesPointer);
602
602
  ```
@@ -750,7 +750,7 @@ contract MyToken is ERC20, Pausable {
750
750
  }
751
751
  }
752
752
 
753
- // OPNet: Custom Pausable base class
753
+ // OP_NET: Custom Pausable base class
754
754
  // export abstract class Pausable extends OP_NET { ... }
755
755
  // this.whenNotPaused(); at start of method
756
756
  ```
@@ -1,6 +1,6 @@
1
1
  # OP20 Token Standard
2
2
 
3
- OP20 is OPNet's fungible token standard, equivalent to Ethereum's ERC20. It provides a complete implementation for creating tokens with transfer, approval, and balance tracking capabilities.
3
+ OP20 is OP_NET's fungible token standard, equivalent to Ethereum's ERC20. It provides a complete implementation for creating tokens with transfer, approval, and balance tracking capabilities.
4
4
 
5
5
  ## Overview
6
6
 
@@ -38,7 +38,7 @@ export class MyToken extends OP20 {
38
38
 
39
39
  ## ERC20 vs OP20 Comparison
40
40
 
41
- | Feature | ERC20 (Solidity) | OP20 (OPNet) |
41
+ | Feature | ERC20 (Solidity) | OP20 (OP_NET) |
42
42
  |---------|------------------|--------------|
43
43
  | Language | Solidity | AssemblyScript |
44
44
  | Runtime | EVM | WASM |
@@ -286,7 +286,7 @@ flowchart LR
286
286
  <table>
287
287
  <tr>
288
288
  <th>ERC20 (Solidity)</th>
289
- <th>OP20 (OPNet)</th>
289
+ <th>OP20 (OP_NET)</th>
290
290
  </tr>
291
291
  <tr>
292
292
  <td>
@@ -39,7 +39,7 @@ export class MyToken extends OP20S {
39
39
 
40
40
  ## ERC20Permit vs OP20S Comparison
41
41
 
42
- | Feature | ERC20Permit (EIP-2612) | OP20S (OPNet) |
42
+ | Feature | ERC20Permit (EIP-2612) | OP20S (OP_NET) |
43
43
  |---------|------------------------|---------------|
44
44
  | Language | Solidity | AssemblyScript |
45
45
  | Signature Type | ECDSA (v, r, s) | Schnorr, ECDSA (deprecated), or ML-DSA |
@@ -327,7 +327,7 @@ contract.permit(..., nonce=0, signature0); // FAILS - nonce mismatch
327
327
  <table>
328
328
  <tr>
329
329
  <th>ERC20Permit (Solidity)</th>
330
- <th>OP20S (OPNet)</th>
330
+ <th>OP20S (OP_NET)</th>
331
331
  </tr>
332
332
  <tr>
333
333
  <td>
@@ -1,6 +1,6 @@
1
1
  # OP721 NFT Standard
2
2
 
3
- OP721 is OPNet's non-fungible token standard, equivalent to Ethereum's ERC721. It provides a complete implementation for creating NFTs with ownership tracking, transfers, approvals, and metadata management.
3
+ OP721 is OP_NET's non-fungible token standard, equivalent to Ethereum's ERC721. It provides a complete implementation for creating NFTs with ownership tracking, transfers, approvals, and metadata management.
4
4
 
5
5
  ## Overview
6
6
 
@@ -33,7 +33,7 @@ export class MyNFT extends OP721 {
33
33
 
34
34
  ## ERC721 vs OP721 Comparison
35
35
 
36
- | Feature | ERC721 (Solidity) | OP721 (OPNet) |
36
+ | Feature | ERC721 (Solidity) | OP721 (OP_NET) |
37
37
  |---------|-------------------|---------------|
38
38
  | Language | Solidity | AssemblyScript |
39
39
  | Runtime | EVM | WASM |
@@ -340,7 +340,7 @@ stateDiagram-v2
340
340
  <table>
341
341
  <tr>
342
342
  <th>ERC721 (Solidity)</th>
343
- <th>OP721 (OPNet)</th>
343
+ <th>OP721 (OP_NET)</th>
344
344
  </tr>
345
345
  <tr>
346
346
  <td>
@@ -31,9 +31,9 @@ export class MyContract extends ReentrancyGuard {
31
31
  }
32
32
  ```
33
33
 
34
- ## OpenZeppelin vs OPNet ReentrancyGuard
34
+ ## OpenZeppelin vs OP_NET ReentrancyGuard
35
35
 
36
- | Feature | OpenZeppelin (Solidity) | OPNet ReentrancyGuard |
36
+ | Feature | OpenZeppelin (Solidity) | OP_NET ReentrancyGuard |
37
37
  |---------|-------------------------|----------------------|
38
38
  | Protection Scope | Per-function (`nonReentrant` modifier) | All methods by default |
39
39
  | Opt-in/Opt-out | Opt-in per function | Opt-out via `isSelectorExcluded` |
@@ -529,8 +529,6 @@ The base `ReentrancyGuard` automatically excludes standard token receiver callba
529
529
  // Built-in exclusions in ReentrancyGuard base class:
530
530
  // - ON_OP20_RECEIVED_SELECTOR
531
531
  // - ON_OP721_RECEIVED_SELECTOR
532
- // - ON_OP1155_RECEIVED_MAGIC
533
- // - ON_OP1155_BATCH_RECEIVED_MAGIC
534
532
  ```
535
533
 
536
534
  You can override `isSelectorExcluded` to add custom exclusions:
@@ -564,7 +562,7 @@ export class MyContract extends ReentrancyGuard {
564
562
  <table>
565
563
  <tr>
566
564
  <th>OpenZeppelin ReentrancyGuard</th>
567
- <th>OPNet ReentrancyGuard</th>
565
+ <th>OP_NET ReentrancyGuard</th>
568
566
  </tr>
569
567
  <tr>
570
568
  <td>
@@ -615,7 +613,7 @@ export class MyContract extends ReentrancyGuard {
615
613
 
616
614
  Key differences:
617
615
  - Solidity: Explicit `nonReentrant` modifier per function
618
- - OPNet: All methods protected by default (opt-out via `isSelectorExcluded`)
616
+ - OP_NET: All methods protected by default (opt-out via `isSelectorExcluded`)
619
617
 
620
618
  ## Best Practices
621
619
 
@@ -731,7 +729,7 @@ public getValue(): u256 {
731
729
  return value;
732
730
  }
733
731
 
734
- // In OPNet, the guard is checked at method entry,
732
+ // In OP_NET, the guard is checked at method entry,
735
733
  // so this isn't an issue - just be aware of it
736
734
  ```
737
735
 
@@ -0,0 +1,384 @@
1
+ # Updatable
2
+
3
+ The `Updatable` base class provides a secure update mechanism with configurable timelock protection. Contracts extending `Updatable` 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 [`UpdatablePlugin`](../advanced/updatable#using-the-updatableplugin) instead. Just call `this.registerPlugin(new UpdatablePlugin(144))` in your constructor - no other code changes needed!
6
+
7
+ ## Overview
8
+
9
+ ```typescript
10
+ import {
11
+ Updatable,
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 Updatable {
21
+ // Set delay: 144 blocks = ~24 hours
22
+ protected readonly updateDelay: u64 = 144;
23
+
24
+ public override execute(method: Selector, calldata: Calldata): BytesWriter {
25
+ switch (method) {
26
+ case encodeSelector('submitUpdate'):
27
+ return this.submitUpdate(calldata.readAddress());
28
+ case encodeSelector('applyUpdate'): {
29
+ const sourceAddress = calldata.readAddress();
30
+ const updateCalldata = calldata.readBytesWithLength();
31
+ return this.applyUpdate(sourceAddress, updateCalldata);
32
+ }
33
+ case encodeSelector('cancelUpdate'):
34
+ return this.cancelUpdate();
35
+ default:
36
+ return super.execute(method, calldata);
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Class Reference
43
+
44
+ ### Properties
45
+
46
+ | Property | Type | Description |
47
+ |----------|------|-------------|
48
+ | `updateDelay` | `u64` | Blocks to wait before update can be applied (default: 144 = ~24h) |
49
+ | `pendingUpdateAddress` | `Address` | Source address of pending update (zero if none) |
50
+ | `pendingUpdateBlock` | `u64` | Block when update was submitted (0 if none) |
51
+ | `updateEffectiveBlock` | `u64` | Block when update can be applied (0 if none) |
52
+ | `hasPendingUpdate` | `bool` | Whether an update is pending |
53
+ | `canApplyUpdate` | `bool` | Whether the delay has elapsed |
54
+
55
+ ### Methods
56
+
57
+ #### submitUpdate
58
+
59
+ Submits an update for timelock. Only callable by deployer.
60
+
61
+ ```typescript
62
+ protected submitUpdate(sourceAddress: Address): BytesWriter
63
+ ```
64
+
65
+ **Parameters:**
66
+ - `sourceAddress`: The address of the contract containing the new bytecode
67
+
68
+ **Reverts if:**
69
+ - Caller is not the deployer
70
+ - Source is not a deployed contract
71
+ - An update is already pending
72
+
73
+ **Emits:** `UpdateSubmitted(sourceAddress, submitBlock, effectiveBlock)`
74
+
75
+ #### applyUpdate
76
+
77
+ Applies a pending update after the delay has passed. Only callable by deployer.
78
+
79
+ ```typescript
80
+ protected applyUpdate(sourceAddress: Address, calldata: BytesWriter): BytesWriter
81
+ ```
82
+
83
+ **Parameters:**
84
+ - `sourceAddress`: The source contract address (must match pending)
85
+ - `calldata`: Data passed to the `onUpdate` hook of the new contract
86
+
87
+ **Reverts if:**
88
+ - Caller is not the deployer
89
+ - No update is pending
90
+ - Delay has not elapsed
91
+ - Address does not match pending update
92
+
93
+ **Emits:** `UpdateApplied(sourceAddress, appliedAtBlock)`
94
+
95
+ #### cancelUpdate
96
+
97
+ Cancels a pending update. Only callable by deployer.
98
+
99
+ ```typescript
100
+ protected cancelUpdate(): BytesWriter
101
+ ```
102
+
103
+ **Reverts if:**
104
+ - Caller is not the deployer
105
+ - No update is pending
106
+
107
+ **Emits:** `UpdateCancelled(sourceAddress, cancelledAtBlock)`
108
+
109
+ ## Events
110
+
111
+ ### UpdateSubmittedEvent
112
+
113
+ Emitted when an update is submitted.
114
+
115
+ ```typescript
116
+ class UpdateSubmittedEvent extends NetEvent {
117
+ constructor(
118
+ sourceAddress: Address, // Contract with new bytecode
119
+ submitBlock: u64, // Block when submitted
120
+ effectiveBlock: u64 // Block when can be applied
121
+ )
122
+ }
123
+ ```
124
+
125
+ ### UpdateAppliedEvent
126
+
127
+ Emitted when an update is applied.
128
+
129
+ ```typescript
130
+ class UpdateAppliedEvent extends NetEvent {
131
+ constructor(
132
+ sourceAddress: Address, // Contract with new bytecode
133
+ appliedAtBlock: u64 // Block when applied
134
+ )
135
+ }
136
+ ```
137
+
138
+ ### UpdateCancelledEvent
139
+
140
+ Emitted when a pending update is cancelled.
141
+
142
+ ```typescript
143
+ class UpdateCancelledEvent extends NetEvent {
144
+ constructor(
145
+ sourceAddress: Address, // Cancelled source contract
146
+ cancelledAtBlock: u64 // Block when cancelled
147
+ )
148
+ }
149
+ ```
150
+
151
+ ## Usage Patterns
152
+
153
+ ### Basic Updatable Contract
154
+
155
+ ```typescript
156
+ @final
157
+ export class SimpleUpdatable extends Updatable {
158
+ protected readonly updateDelay: u64 = 144; // ~1 day
159
+
160
+ public override execute(method: Selector, calldata: Calldata): BytesWriter {
161
+ switch (method) {
162
+ case encodeSelector('submitUpdate'):
163
+ return this.submitUpdate(calldata.readAddress());
164
+ case encodeSelector('applyUpdate'): {
165
+ const sourceAddress = calldata.readAddress();
166
+ const updateCalldata = calldata.readBytesWithLength();
167
+ return this.applyUpdate(sourceAddress, updateCalldata);
168
+ }
169
+ case encodeSelector('cancelUpdate'):
170
+ return this.cancelUpdate();
171
+ default:
172
+ return super.execute(method, calldata);
173
+ }
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### With Update Status Views
179
+
180
+ ```typescript
181
+ @final
182
+ export class UpdatableWithViews extends Updatable {
183
+ protected readonly updateDelay: u64 = 1008; // ~1 week
184
+
185
+ public override execute(method: Selector, calldata: Calldata): BytesWriter {
186
+ switch (method) {
187
+ // Update actions
188
+ case encodeSelector('submitUpdate'):
189
+ return this.submitUpdate(calldata.readAddress());
190
+ case encodeSelector('applyUpdate'): {
191
+ const sourceAddress = calldata.readAddress();
192
+ const updateCalldata = calldata.readBytesWithLength();
193
+ return this.applyUpdate(sourceAddress, updateCalldata);
194
+ }
195
+ case encodeSelector('cancelUpdate'):
196
+ return this.cancelUpdate();
197
+
198
+ // View methods
199
+ case encodeSelector('getPendingUpdate'):
200
+ return this.getPendingUpdate();
201
+ case encodeSelector('getUpdateStatus'):
202
+ return this.getUpdateStatus();
203
+
204
+ default:
205
+ return super.execute(method, calldata);
206
+ }
207
+ }
208
+
209
+ private getPendingUpdate(): BytesWriter {
210
+ const response = new BytesWriter(32);
211
+ response.writeAddress(this.pendingUpdateAddress);
212
+ return response;
213
+ }
214
+
215
+ private getUpdateStatus(): BytesWriter {
216
+ const response = new BytesWriter(17);
217
+ response.writeBoolean(this.hasPendingUpdate);
218
+ response.writeU64(this.pendingUpdateBlock);
219
+ response.writeU64(this.updateEffectiveBlock);
220
+ return response;
221
+ }
222
+ }
223
+ ```
224
+
225
+ ### Emergency Updates (Not Recommended)
226
+
227
+ For contracts that need faster updates (use with caution):
228
+
229
+ ```typescript
230
+ @final
231
+ export class QuickUpdatable extends Updatable {
232
+ // Only 6 blocks (~1 hour) - use only for emergencies
233
+ protected readonly updateDelay: u64 = 6;
234
+
235
+ // ... rest of implementation
236
+ }
237
+ ```
238
+
239
+ ## Security Considerations
240
+
241
+ ### 1. Delay Selection
242
+
243
+ Choose an appropriate delay based on your contract's risk profile:
244
+
245
+ | Contract Type | Recommended Delay |
246
+ |---------------|-------------------|
247
+ | Test/Development | 1-6 blocks |
248
+ | Standard DeFi | 144 blocks (~24 hours) |
249
+ | High-value vaults | 1008 blocks (~1 week) |
250
+ | Governance contracts | 4320 blocks (~1 month) |
251
+
252
+ ### 2. Source Validation
253
+
254
+ The `submitUpdate` function validates that the source is a deployed contract. This prevents:
255
+ - Submitting non-existent addresses
256
+ - Last-minute malicious deployments
257
+
258
+ ### 3. Address Match Verification
259
+
260
+ The `applyUpdate` function requires the address to match the pending update. This prevents:
261
+ - Front-running attacks
262
+ - Address substitution attacks
263
+
264
+ ### 4. Storage Compatibility
265
+
266
+ When upgrading, ensure storage layout compatibility:
267
+
268
+ ```typescript
269
+ // V1 - Original
270
+ class ContractV1 extends Updatable {
271
+ private ptr1: u16 = Blockchain.nextPointer; // Pointer 1
272
+ private ptr2: u16 = Blockchain.nextPointer; // Pointer 2
273
+ }
274
+
275
+ // V2 - Add new pointers at the END
276
+ class ContractV2 extends Updatable {
277
+ private ptr1: u16 = Blockchain.nextPointer; // Pointer 1 (same)
278
+ private ptr2: u16 = Blockchain.nextPointer; // Pointer 2 (same)
279
+ private ptr3: u16 = Blockchain.nextPointer; // Pointer 3 (NEW)
280
+ }
281
+ ```
282
+
283
+ ## Update Workflow
284
+
285
+ ```
286
+ 1. Deploy new bytecode contract
287
+ └─> Returns: newContractAddress
288
+
289
+ 2. Submit update
290
+ └─> submitUpdate(newContractAddress)
291
+ └─> Emits: UpdateSubmitted
292
+
293
+ 3. Wait for delay
294
+ └─> Users can monitor and exit
295
+
296
+ 4. Apply update
297
+ └─> applyUpdate(newContractAddress)
298
+ └─> Emits: UpdateApplied
299
+ └─> VM calls onUpdate() on new bytecode
300
+ └─> New bytecode active next block
301
+
302
+ 5. (Optional) Discard source contract
303
+ └─> Source contract can be abandoned
304
+ ```
305
+
306
+ ### The onUpdate Hook
307
+
308
+ Override `onUpdate` in your new contract version to perform migrations:
309
+
310
+ ```typescript
311
+ @final
312
+ export class MyContractV2 extends Updatable {
313
+ protected readonly updateDelay: u64 = 144;
314
+
315
+ // New storage added in V2
316
+ private newFeaturePointer: u16 = Blockchain.nextPointer;
317
+ private _newFeature: StoredU256;
318
+
319
+ public constructor() {
320
+ super();
321
+ this._newFeature = new StoredU256(this.newFeaturePointer, EMPTY_POINTER);
322
+ }
323
+
324
+ public override onUpdate(calldata: Calldata): void {
325
+ super.onUpdate(calldata);
326
+ // Initialize new storage
327
+ this._newFeature.value = u256.fromU64(100);
328
+ }
329
+
330
+ // ... execute() and other methods
331
+ }
332
+ ```
333
+
334
+ See [The onUpdate Lifecycle Hook](../advanced/updatable#the-onupdate-lifecycle-hook) for more details.
335
+
336
+ ## Combining with Other Base Classes
337
+
338
+ ### Updatable + ReentrancyGuard
339
+
340
+ ```typescript
341
+ // Create a combined base class
342
+ class UpdatableWithReentrancy extends Updatable {
343
+ protected readonly reentrancyLevel: ReentrancyLevel = ReentrancyLevel.STANDARD;
344
+ private _locked: StoredBoolean;
345
+
346
+ protected constructor() {
347
+ super();
348
+ this._locked = new StoredBoolean(Blockchain.nextPointer, false);
349
+ }
350
+
351
+ protected nonReentrant(): void {
352
+ if (this._locked.value) {
353
+ throw new Revert('ReentrancyGuard: LOCKED');
354
+ }
355
+ this._locked.value = true;
356
+ }
357
+
358
+ protected releaseGuard(): void {
359
+ this._locked.value = false;
360
+ }
361
+ }
362
+
363
+ @final
364
+ export class SecureUpdatableVault extends UpdatableWithReentrancy {
365
+ // Implementation with both update and reentrancy protection
366
+ }
367
+ ```
368
+
369
+ ## Solidity Comparison
370
+
371
+ | Feature | OpenZeppelin UUPS | OP_NET Updatable |
372
+ |---------|-------------------|-------------------|
373
+ | Update mechanism | delegatecall | Native bytecode replacement |
374
+ | Storage location | Implementation contract | Same contract |
375
+ | Proxy overhead | Yes | No |
376
+ | Timelock | Separate contract (optional) | Built-in |
377
+ | Events | Custom | Built-in |
378
+ | Cancel update | Custom implementation | Built-in |
379
+
380
+ ---
381
+
382
+ **Navigation:**
383
+ - Previous: [ReentrancyGuard](./reentrancy-guard.md)
384
+ - Next: [Address Type](../types/address.md)