@btc-vision/btc-runtime 1.10.10 → 1.10.11
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/LICENSE +190 -0
- package/README.md +258 -137
- package/SECURITY.md +226 -0
- package/docs/README.md +614 -0
- package/docs/advanced/bitcoin-scripts.md +939 -0
- package/docs/advanced/cross-contract-calls.md +579 -0
- package/docs/advanced/plugins.md +1006 -0
- package/docs/advanced/quantum-resistance.md +660 -0
- package/docs/advanced/signature-verification.md +715 -0
- package/docs/api-reference/blockchain.md +729 -0
- package/docs/api-reference/events.md +642 -0
- package/docs/api-reference/op20.md +902 -0
- package/docs/api-reference/op721.md +819 -0
- package/docs/api-reference/safe-math.md +510 -0
- package/docs/api-reference/storage.md +840 -0
- package/docs/contracts/op-net-base.md +786 -0
- package/docs/contracts/op20-token.md +687 -0
- package/docs/contracts/op20s-signatures.md +614 -0
- package/docs/contracts/op721-nft.md +785 -0
- package/docs/contracts/reentrancy-guard.md +787 -0
- package/docs/core-concepts/blockchain-environment.md +724 -0
- package/docs/core-concepts/decorators.md +466 -0
- package/docs/core-concepts/events.md +652 -0
- package/docs/core-concepts/pointers.md +391 -0
- package/docs/core-concepts/security.md +473 -0
- package/docs/core-concepts/storage-system.md +969 -0
- package/docs/examples/basic-token.md +745 -0
- package/docs/examples/nft-with-reservations.md +1440 -0
- package/docs/examples/oracle-integration.md +1212 -0
- package/docs/examples/stablecoin.md +1180 -0
- package/docs/getting-started/first-contract.md +575 -0
- package/docs/getting-started/installation.md +384 -0
- package/docs/getting-started/project-structure.md +630 -0
- package/docs/storage/memory-maps.md +764 -0
- package/docs/storage/stored-arrays.md +778 -0
- package/docs/storage/stored-maps.md +758 -0
- package/docs/storage/stored-primitives.md +655 -0
- package/docs/types/address.md +773 -0
- package/docs/types/bytes-writer-reader.md +938 -0
- package/docs/types/calldata.md +744 -0
- package/docs/types/safe-math.md +446 -0
- package/package.json +51 -26
- package/runtime/memory/MapOfMap.ts +1 -0
- package/LICENSE.md +0 -21
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Security is paramount in smart contract development. This guide covers OPNet's security mechanisms and best practices for writing secure contracts.
|
|
4
|
+
|
|
5
|
+
## Security Mechanisms
|
|
6
|
+
|
|
7
|
+
OPNet provides several built-in security features:
|
|
8
|
+
|
|
9
|
+
| Feature | Description |
|
|
10
|
+
|---------|-------------|
|
|
11
|
+
| **SafeMath** | Overflow/underflow protection |
|
|
12
|
+
| **ReentrancyGuard** | Reentrancy attack prevention |
|
|
13
|
+
| **Access Control** | Role-based authorization |
|
|
14
|
+
| **Input Validation** | Calldata parsing with bounds checks |
|
|
15
|
+
| **Storage Safety** | SHA256-hashed storage keys |
|
|
16
|
+
|
|
17
|
+
## SafeMath
|
|
18
|
+
|
|
19
|
+
### The Problem
|
|
20
|
+
|
|
21
|
+
Integer overflow/underflow can cause critical bugs:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// DANGEROUS: Native arithmetic can overflow silently
|
|
25
|
+
const a: u256 = u256.Max;
|
|
26
|
+
const b: u256 = u256.One;
|
|
27
|
+
const result = a + b; // Wraps to 0!
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### The Solution
|
|
31
|
+
|
|
32
|
+
Always use SafeMath for arithmetic:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { SafeMath } from '@btc-vision/btc-runtime/runtime';
|
|
36
|
+
import { u256 } from '@btc-vision/as-bignum/assembly';
|
|
37
|
+
|
|
38
|
+
const a = u256.fromU64(100);
|
|
39
|
+
const b = u256.fromU64(50);
|
|
40
|
+
|
|
41
|
+
// Safe operations
|
|
42
|
+
const sum = SafeMath.add(a, b); // Reverts on overflow
|
|
43
|
+
const diff = SafeMath.sub(a, b); // Reverts on underflow
|
|
44
|
+
const product = SafeMath.mul(a, b); // Reverts on overflow
|
|
45
|
+
const quotient = SafeMath.div(a, b); // Reverts on division by zero
|
|
46
|
+
const remainder = SafeMath.mod(a, b); // Reverts on division by zero
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Solidity Comparison
|
|
50
|
+
|
|
51
|
+
In Solidity 0.8+, arithmetic operations revert on overflow/underflow by default. OPNet achieves the same behavior through SafeMath:
|
|
52
|
+
|
|
53
|
+
```solidity
|
|
54
|
+
// Solidity 0.8+ - automatic overflow protection
|
|
55
|
+
uint256 result = a + b; // Reverts on overflow
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// OPNet - explicit SafeMath usage
|
|
60
|
+
const result = SafeMath.add(a, b); // Reverts on overflow
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### SafeMath Operations
|
|
64
|
+
|
|
65
|
+
| Operation | Method | Behavior |
|
|
66
|
+
|-----------|--------|----------|
|
|
67
|
+
| Addition | `SafeMath.add(a, b)` | Reverts on overflow |
|
|
68
|
+
| Subtraction | `SafeMath.sub(a, b)` | Reverts on underflow |
|
|
69
|
+
| Multiplication | `SafeMath.mul(a, b)` | Reverts on overflow |
|
|
70
|
+
| Division | `SafeMath.div(a, b)` | Reverts on zero divisor |
|
|
71
|
+
| Modulo | `SafeMath.mod(a, b)` | Reverts on zero divisor |
|
|
72
|
+
| Power | `SafeMath.pow(base, exp)` | Reverts on overflow |
|
|
73
|
+
| Square Root | `SafeMath.sqrt(a)` | Newton-Raphson method |
|
|
74
|
+
|
|
75
|
+
See [SafeMath API](../api-reference/safe-math.md) for complete reference.
|
|
76
|
+
|
|
77
|
+
## Reentrancy Protection
|
|
78
|
+
|
|
79
|
+
### The Problem
|
|
80
|
+
|
|
81
|
+
Reentrancy attacks occur when a contract calls back into itself before completing:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
1. User calls withdraw()
|
|
85
|
+
2. Contract sends funds to User
|
|
86
|
+
3. User's receive function calls withdraw() again
|
|
87
|
+
4. Contract sends funds again (before updating balance)
|
|
88
|
+
5. Repeat until drained
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Reentrancy Attack Sequence
|
|
92
|
+
|
|
93
|
+
```mermaid
|
|
94
|
+
sequenceDiagram
|
|
95
|
+
participant Attacker
|
|
96
|
+
participant VulnerableContract
|
|
97
|
+
participant AttackerContract
|
|
98
|
+
|
|
99
|
+
Attacker->>VulnerableContract: withdraw()
|
|
100
|
+
activate VulnerableContract
|
|
101
|
+
|
|
102
|
+
Note over VulnerableContract: balance = 100<br/>Check balance
|
|
103
|
+
|
|
104
|
+
VulnerableContract->>AttackerContract: Transfer 100 tokens
|
|
105
|
+
activate AttackerContract
|
|
106
|
+
|
|
107
|
+
Note over AttackerContract: Receive callback triggered
|
|
108
|
+
|
|
109
|
+
AttackerContract->>VulnerableContract: withdraw() [RE-ENTER!]
|
|
110
|
+
activate VulnerableContract
|
|
111
|
+
|
|
112
|
+
Note over VulnerableContract: balance still = 100<br/>Check balance [BUG!]
|
|
113
|
+
|
|
114
|
+
VulnerableContract->>AttackerContract: Transfer 100 tokens AGAIN
|
|
115
|
+
deactivate VulnerableContract
|
|
116
|
+
|
|
117
|
+
AttackerContract-->>VulnerableContract: Return
|
|
118
|
+
deactivate AttackerContract
|
|
119
|
+
|
|
120
|
+
Note over VulnerableContract: balance = 0<br/>(Too late!)
|
|
121
|
+
|
|
122
|
+
VulnerableContract-->>Attacker: Complete
|
|
123
|
+
deactivate VulnerableContract
|
|
124
|
+
|
|
125
|
+
Note over Attacker: Stole 200 tokens!<br/>Expected: 100
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### The Solution: ReentrancyGuard
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { ReentrancyGuard, ReentrancyLevel } from '@btc-vision/btc-runtime/runtime';
|
|
132
|
+
|
|
133
|
+
@final
|
|
134
|
+
export class MyContract extends ReentrancyGuard {
|
|
135
|
+
// Override the reentrancy level (STANDARD is the default)
|
|
136
|
+
protected override readonly reentrancyLevel: ReentrancyLevel = ReentrancyLevel.STANDARD;
|
|
137
|
+
|
|
138
|
+
public constructor() {
|
|
139
|
+
super();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@method()
|
|
143
|
+
public withdraw(calldata: Calldata): BytesWriter {
|
|
144
|
+
// ReentrancyGuard automatically protects this method
|
|
145
|
+
const amount = this.balances.get(Blockchain.tx.sender);
|
|
146
|
+
|
|
147
|
+
// Even if external call tries to re-enter, it will fail
|
|
148
|
+
this.balances.set(Blockchain.tx.sender, u256.Zero);
|
|
149
|
+
// ... transfer funds ...
|
|
150
|
+
|
|
151
|
+
return new BytesWriter(0);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### ReentrancyGuard Mechanism Flow
|
|
157
|
+
|
|
158
|
+
```mermaid
|
|
159
|
+
---
|
|
160
|
+
config:
|
|
161
|
+
theme: dark
|
|
162
|
+
---
|
|
163
|
+
flowchart LR
|
|
164
|
+
Start["Method Called"] --> Check{"Guard Active?"}
|
|
165
|
+
Check -->|Yes| Revert["REVERT"]
|
|
166
|
+
Check -->|No| SetGuard["Set Guard Flag"]
|
|
167
|
+
SetGuard --> Execute["Execute Logic"]
|
|
168
|
+
Execute --> External{"External Call?"}
|
|
169
|
+
External -->|Yes| Call["Call External"]
|
|
170
|
+
Call --> Detect{"Re-enter?"}
|
|
171
|
+
Detect -->|Yes| Block["REVERT: Blocked"]
|
|
172
|
+
Detect -->|No| Clear["Clear Guard"]
|
|
173
|
+
External -->|No| Clear
|
|
174
|
+
Clear --> Success["Transaction Success"]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Guard Modes
|
|
178
|
+
|
|
179
|
+
| Mode | Description | Use Case |
|
|
180
|
+
|------|-------------|----------|
|
|
181
|
+
| `ReentrancyLevel.STANDARD` | Uses boolean lock, strict mutual exclusion | Default for most contracts |
|
|
182
|
+
| `ReentrancyLevel.CALLBACK` | Uses depth counter, still blocks reentrancy | Depth tracking use cases |
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// STANDARD: No re-entry allowed, uses boolean lock (default)
|
|
186
|
+
protected override readonly reentrancyLevel: ReentrancyLevel = ReentrancyLevel.STANDARD;
|
|
187
|
+
|
|
188
|
+
// CALLBACK: No re-entry allowed, uses depth counter for tracking
|
|
189
|
+
protected override readonly reentrancyLevel: ReentrancyLevel = ReentrancyLevel.CALLBACK;
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Guard Mode Decision Tree
|
|
193
|
+
|
|
194
|
+
```mermaid
|
|
195
|
+
---
|
|
196
|
+
config:
|
|
197
|
+
theme: dark
|
|
198
|
+
---
|
|
199
|
+
flowchart LR
|
|
200
|
+
Start{"External Calls?"}
|
|
201
|
+
Start -->|No| None["No Guard Needed"]
|
|
202
|
+
Start -->|Yes| Tracking{"Need Depth Tracking?"}
|
|
203
|
+
Tracking -->|No| Standard["STANDARD Mode"]
|
|
204
|
+
Tracking -->|Yes| CallbackMode["CALLBACK Mode"]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Note: Both modes block reentrancy. STANDARD uses a boolean lock; CALLBACK uses a depth counter.
|
|
208
|
+
|
|
209
|
+
See [ReentrancyGuard](../contracts/reentrancy-guard.md) for detailed usage.
|
|
210
|
+
|
|
211
|
+
## Access Control
|
|
212
|
+
|
|
213
|
+
### onlyDeployer Pattern
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
@final
|
|
217
|
+
export class MyContract extends OP_NET {
|
|
218
|
+
public constructor() {
|
|
219
|
+
super();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@method()
|
|
223
|
+
public adminFunction(calldata: Calldata): BytesWriter {
|
|
224
|
+
// Only deployer can call
|
|
225
|
+
this.onlyDeployer(Blockchain.tx.sender);
|
|
226
|
+
|
|
227
|
+
// Admin logic...
|
|
228
|
+
return new BytesWriter(0);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Solidity Comparison
|
|
234
|
+
|
|
235
|
+
```solidity
|
|
236
|
+
// Solidity
|
|
237
|
+
modifier onlyOwner() {
|
|
238
|
+
require(msg.sender == owner, "Not owner");
|
|
239
|
+
_;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// OPNet
|
|
245
|
+
protected onlyOwner(): void {
|
|
246
|
+
if (!Blockchain.tx.sender.equals(this.owner.value)) {
|
|
247
|
+
throw new Revert('Not owner');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Custom Roles
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
@final
|
|
256
|
+
export class MyContract extends OP_NET {
|
|
257
|
+
private readonly adminPointer: u16 = Blockchain.nextPointer;
|
|
258
|
+
private readonly admin: StoredAddress = new StoredAddress(this.adminPointer, Address.zero());
|
|
259
|
+
|
|
260
|
+
private readonly mintersPointer: u16 = Blockchain.nextPointer;
|
|
261
|
+
private readonly minters: AddressMemoryMap;
|
|
262
|
+
|
|
263
|
+
public constructor() {
|
|
264
|
+
super();
|
|
265
|
+
this.minters = new AddressMemoryMap(this.mintersPointer);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
protected onlyAdmin(): void {
|
|
269
|
+
if (!Blockchain.tx.sender.equals(this.admin.value)) {
|
|
270
|
+
throw new Revert('Not admin');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
protected onlyMinter(): void {
|
|
275
|
+
if (this.minters.get(Blockchain.tx.sender).isZero()) {
|
|
276
|
+
throw new Revert('Not minter');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@method()
|
|
281
|
+
public mint(calldata: Calldata): BytesWriter {
|
|
282
|
+
this.onlyMinter();
|
|
283
|
+
// ...
|
|
284
|
+
return new BytesWriter(0);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
@method()
|
|
288
|
+
public setMinter(calldata: Calldata): BytesWriter {
|
|
289
|
+
this.onlyAdmin();
|
|
290
|
+
const minter = calldata.readAddress();
|
|
291
|
+
this.minters.set(minter, u256.One);
|
|
292
|
+
return new BytesWriter(0);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Input Validation
|
|
298
|
+
|
|
299
|
+
### Validate All Inputs
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
@method()
|
|
303
|
+
public transfer(calldata: Calldata): BytesWriter {
|
|
304
|
+
const to = calldata.readAddress();
|
|
305
|
+
const amount = calldata.readU256();
|
|
306
|
+
|
|
307
|
+
// Validate recipient
|
|
308
|
+
if (to.equals(Address.zero())) {
|
|
309
|
+
throw new Revert('Cannot transfer to zero address');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Validate amount
|
|
313
|
+
if (amount.isZero()) {
|
|
314
|
+
throw new Revert('Amount must be greater than zero');
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Validate balance
|
|
318
|
+
const balance = this.balances.get(Blockchain.tx.sender);
|
|
319
|
+
if (balance < amount) {
|
|
320
|
+
throw new Revert('Insufficient balance');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ... proceed with transfer
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Common Validations
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
// Zero address check
|
|
331
|
+
if (address.equals(Address.zero())) {
|
|
332
|
+
throw new Revert('Invalid address');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Self-transfer check
|
|
336
|
+
if (from.equals(to)) {
|
|
337
|
+
throw new Revert('Cannot transfer to self');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Amount checks
|
|
341
|
+
if (amount.isZero()) {
|
|
342
|
+
throw new Revert('Amount is zero');
|
|
343
|
+
}
|
|
344
|
+
if (amount > maxAmount) {
|
|
345
|
+
throw new Revert('Amount exceeds maximum');
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Array bounds
|
|
349
|
+
if (index >= array.length) {
|
|
350
|
+
throw new Revert('Index out of bounds');
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Common Vulnerabilities
|
|
355
|
+
|
|
356
|
+
### 1. Integer Overflow/Underflow
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
// VULNERABLE
|
|
360
|
+
const newBalance = balance + amount; // Can overflow!
|
|
361
|
+
|
|
362
|
+
// SAFE
|
|
363
|
+
const newBalance = SafeMath.add(balance, amount);
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 2. Reentrancy
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
// VULNERABLE
|
|
370
|
+
@method()
|
|
371
|
+
public withdraw(): void {
|
|
372
|
+
const amount = balances.get(sender);
|
|
373
|
+
externalCall(sender, amount); // Can re-enter!
|
|
374
|
+
balances.set(sender, u256.Zero);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// SAFE (Checks-Effects-Interactions pattern)
|
|
378
|
+
@method()
|
|
379
|
+
public withdraw(): void {
|
|
380
|
+
const amount = balances.get(sender);
|
|
381
|
+
balances.set(sender, u256.Zero); // Update state first
|
|
382
|
+
externalCall(sender, amount); // Then make external call
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 3. Access Control Bypass
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// VULNERABLE
|
|
390
|
+
@method()
|
|
391
|
+
public mint(calldata: Calldata): void {
|
|
392
|
+
// No access control!
|
|
393
|
+
this._mint(calldata.readAddress(), calldata.readU256());
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// SAFE
|
|
397
|
+
@method()
|
|
398
|
+
public mint(calldata: Calldata): void {
|
|
399
|
+
this.onlyDeployer(Blockchain.tx.sender);
|
|
400
|
+
this._mint(calldata.readAddress(), calldata.readU256());
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### 4. tx.origin Authentication
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
// VULNERABLE (phishing attack possible)
|
|
408
|
+
@method()
|
|
409
|
+
public withdraw(): void {
|
|
410
|
+
if (Blockchain.tx.origin.equals(owner)) { // WRONG!
|
|
411
|
+
// ...
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// SAFE
|
|
416
|
+
@method()
|
|
417
|
+
public withdraw(): void {
|
|
418
|
+
if (Blockchain.tx.sender.equals(owner)) { // Correct
|
|
419
|
+
// ...
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### 5. Floating Point
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// VULNERABLE (non-deterministic)
|
|
428
|
+
const price: f64 = 1.5; // NEVER use floats!
|
|
429
|
+
|
|
430
|
+
// SAFE (fixed-point)
|
|
431
|
+
const PRECISION: u256 = u256.fromU64(1_000_000);
|
|
432
|
+
const price: u256 = SafeMath.mul(u256.fromU64(15), SafeMath.div(PRECISION, u256.fromU64(10)));
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Security Checklist
|
|
436
|
+
|
|
437
|
+
Before deploying, verify:
|
|
438
|
+
|
|
439
|
+
- [ ] All arithmetic uses SafeMath
|
|
440
|
+
- [ ] ReentrancyGuard on sensitive functions
|
|
441
|
+
- [ ] Access control on admin functions
|
|
442
|
+
- [ ] Input validation on all public methods
|
|
443
|
+
- [ ] No floating-point arithmetic
|
|
444
|
+
- [ ] No tx.origin for authentication
|
|
445
|
+
- [ ] Events emitted for state changes
|
|
446
|
+
- [ ] Tests cover edge cases
|
|
447
|
+
- [ ] No hardcoded secrets
|
|
448
|
+
|
|
449
|
+
## Audit Information
|
|
450
|
+
|
|
451
|
+
btc-runtime has been audited by [Verichains](https://verichains.io). The audit covered:
|
|
452
|
+
|
|
453
|
+
- Contract standards (OP20, OP721)
|
|
454
|
+
- Storage system security
|
|
455
|
+
- Cryptographic implementations
|
|
456
|
+
- SafeMath operations
|
|
457
|
+
- ReentrancyGuard mechanisms
|
|
458
|
+
|
|
459
|
+
See [SECURITY.md](../../SECURITY.md) for full audit details.
|
|
460
|
+
|
|
461
|
+
## Reporting Vulnerabilities
|
|
462
|
+
|
|
463
|
+
If you discover a security issue:
|
|
464
|
+
|
|
465
|
+
1. **DO NOT** open a public GitHub issue
|
|
466
|
+
2. Report via [GitHub Security Advisories](https://github.com/btc-vision/btc-runtime/security/advisories)
|
|
467
|
+
3. Allow time for fix before disclosure
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
**Navigation:**
|
|
472
|
+
- Previous: [Events](./events.md)
|
|
473
|
+
- Next: [OP_NET Base Contract](../contracts/op-net-base.md)
|