You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<Badgetext="Available since Tact 1.7"variant="tip"size="medium"/>
368
+
<Badgetext="DANGEROUS"title="Applies irreversible modifications to the contract — use only when you know what you are doing!"variant="danger"size="medium"/><p/>
369
+
370
+
```tact
371
+
fun setData(data: Cell);
372
+
```
373
+
374
+
Replaces the current contract's state data [`Cell{:tact}`][cell] with the new `data`. It is useful only in exceptional cases, such as contract upgrades, data migrations, or when processing external messages with a catch-all [`Slice{:tact}`][slice] receiver for maximum efficiency. Otherwise, do **not** use this function, as it immediately and permanently overrides the state with no ability to recover, which can result in the loss of funds and partial or full corruption of the contract's data.
375
+
376
+
:::caution
377
+
378
+
When using this function, make sure that all logical code branches within your receiver end with a call to the [`throw(0){:tact}`](/ref/core-debug#throw) function to terminate the execution of the contract early and prevent the automatic contract's data save implicitly added by Tact after the end of each receiver. Conversely, your manual changes to data made with this function will be lost.
379
+
380
+
:::
381
+
382
+
Usage example:
383
+
384
+
```tact {13}
385
+
contract WalletV4(
386
+
seqno: Int as uint32,
387
+
// ...other parameters...
388
+
) {
389
+
// ...
390
+
external(_: Slice) {
391
+
// ...various prior checks...
392
+
393
+
acceptMessage();
394
+
self.seqno += 1;
395
+
396
+
// Manually saving the contract's state
397
+
setData(self.toCell());
398
+
399
+
// And halting the transaction to prevent a secondary save implicitly
400
+
// added by Tact after the main execution logic of the receiver
401
+
throw(0);
402
+
}
403
+
}
404
+
```
405
+
406
+
:::note
407
+
408
+
Tact automatically saves the contract's state after the end of each receiver's logic even when `return{:tact}` statements are used for early termination. Thus, this function is almost never needed in regular contracts.
409
+
410
+
However, if you intend to use the `throw(0){:tact}` pattern to terminate the compute phase and save the state yourself or you want to replace the data when upgrading the contract, this function becomes useful. That said, make sure to double-check and test cover your every move such that the contract's data won't become corrupt or inadvertently gone.
Copy file name to clipboardExpand all lines: src/stdlib/stdlib/std/internal/contract.tact
+50-1Lines changed: 50 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -99,7 +99,7 @@ struct StateInit {
99
99
///
100
100
/// Checks if the given `address` corresponds to the contract address in the workchain ID 0 (basechain) derived from the `StateInit` `self`. Returns `true` if the addresses match and `false` otherwise.
101
101
///
102
-
/// This function works correctly only for basechain addresses. It may produce false positives or negatives if the specified `address` or the address derived from the `StateInit{:tact}` `self{:tact}` has a non-zero workchain ID.
102
+
/// This function works correctly only for basechain addresses. It may produce false positives or negatives if the specified `address` or the address derived from the `StateInit` `self` has a non-zero workchain ID.
/// Global function. Available since Tact 1.7.0. DANGEROUS: Applies irreversible modifications to the contract — use only when you know what you are doing!
462
+
///
463
+
/// Replaces the current contract's state data [`Cell`][cell] with the new `data`. It is useful only in exceptional cases, such as contract upgrades, data migrations, or when processing external messages with a catch-all [`Slice`][slice] receiver for maximum efficiency. Otherwise, do **not** use this function, as it immediately and permanently overrides the state with no ability to recover, which can result in the loss of funds and partial or full corruption of the contract's data.
464
+
///
465
+
/// #### Caution
466
+
///
467
+
/// When using this function, make sure that all logical code branches within your receiver end with a call to the [`throw(0)`][throw] function to terminate the execution of the contract early and prevent the automatic contract's data save implicitly added by Tact after the end of each receiver. Conversely, your manual changes to data made with this function will be lost.
468
+
///
469
+
/// #### Usage example
470
+
///
471
+
/// ```tact {13}
472
+
/// contract WalletV4(
473
+
/// seqno: Int as uint32,
474
+
/// // ...other parameters...
475
+
/// ) {
476
+
/// // ...
477
+
/// external(_: Slice) {
478
+
/// // ...various prior checks...
479
+
///
480
+
/// acceptMessage();
481
+
/// self.seqno += 1;
482
+
///
483
+
/// // Manually saving the contract's state
484
+
/// setData(self.toCell());
485
+
///
486
+
/// // And halting the transaction to prevent a secondary save implicitly
487
+
/// // added by Tact after the main execution logic of the receiver
488
+
/// throw(0);
489
+
/// }
490
+
/// }
491
+
/// ```
492
+
///
493
+
/// #### Note
494
+
///
495
+
/// Tact automatically saves the contract's state after the end of each receiver's logic even when `return` statements are used for early termination. Thus, this function is almost never needed in regular contracts.
496
+
///
497
+
/// However, if you intend to use the `throw(0)` pattern to terminate the compute phase and save the state yourself or you want to replace the data when upgrading the contract, this function becomes useful. That said, make sure to double-check and test cover your every move such that the contract's data won't become corrupt or inadvertently gone.
0 commit comments