Skip to content

Added information about upgradable smart-contracts and an example #594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions docs/develop/func/cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -1487,3 +1487,76 @@ forall X -> (tuple, (X)) pop_back (tuple t) asm "UNCONS";
.end_cell();
}
```

### How to update the smart contract logic

The smart contract logic is stored in the cells of register `c3` and the persistent storage in the cells of register `c4`. This design allows developers to overwrite the contract logic with set_code and overwrite the existing storage with set_data, allowing for in-place updates without the need for proxy templates.

Below is a simple `СounterV1` smart-contract that has the functionality to increment the counter and update the smart-contract logic.

```func
() recv_internal (slice in_msg_body) {
int op = in_msg_body~load_uint(32);

if (op == op::increase) {
int increase_by = in_msg_body~load_uint(32);
ctx_counter += increase_by;
save_data();
return ();
}

if (op == op::upgrade) {
cell code = in_msg_body~load_ref();
set_code(code);
return ();
}
}
```

After operating the smart-contract, you realize that you are missing the meter reduction feature. You must copy the code of the smart-contract `CounterV1` and next to the `increase` function, add a new `decrease` function. Now your code looks like this:

```func
() recv_internal (slice in_msg_body) {
int op = in_msg_body~load_uint(32);

if (op == op::increase) {
int increase_by = in_msg_body~load_uint(32);
ctx_counter += increase_by;
save_data();
return ();
}

if (op == op::decrease) {
int decrease_by = in_msg_body~load_uint(32);
ctx_counter -= increase_by;
save_data();
return ();
}

if (op == op::upgrade) {
cell code = in_msg_body~load_ref();
set_code(code);
return ();
}
}
```

Once the smart-contract `CounterV2` is ready, you must compile it off-chain into a `cell` and send an upgrade message to the `CounterV1` smart-contract.

```javascript
await contractV1.sendUpgrade(provider.sender(), {
code: await compile('ContractV2'),
value: toNano('0.05'),
});
```

> 💡 Useful links
>
> [Is it possible to re-deploy code to an existing address or does it have to be deployed as a new contract?](/develop/howto/faq#is-it-possible-to-re-deploy-code-to-an-existing-address-or-does-it-have-to-be-deployed-as-a-new-contract)
>
> ["set_code()" in docs](/develop/func/stdlib#set_code)





17 changes: 17 additions & 0 deletions docs/develop/howto/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,23 @@ To protect message chains from being halted at non-existing contracts TON use "b
- [Deploying wallet via TonLib](https://ton.org/docs/develop/dapps/asset-processing/#deploying-wallet)
- [Paying for processing queries and sending responses](https://ton.org/docs/develop/smart-contracts/guidelines/processing)

### Does the upgradability of a smart-contract pose a threat to its users?

Currently, the ability to update smart contracts is a normal practice and is widely used in most modern protocols. This is because updatability allows for bug fixes, adding new features and improving security.

How to mitigate the risks:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vkokosh Could you please fix the numbers in the list?

1. Pay attention to projects with a good reputation and well-known development teams.
1. Reputable projects always conduct independent code audits to make sure the code is safe and reliable. Look for projects that have several completed audits from reputable auditing firms.
1. An active community and positive feedback can serve as an additional indicator of a project's reliability.
1. Examine exactly how the project implements the update process. The more transparent and decentralized the process, the less risk to users.

### How can users be sure that the contract owner will not change certain conditions (via an update)?

The contract must be verified, this allows you to check the source code and ensure that there is no update logic to ensure it remains unchanged. If the contract does indeed lack mechanisms to change the code, the terms of the contract will remain unchanged after deployment.

Sometimes the logic for updating may exist, but the rights to change the code may be moved to an "empty" address, which also precludes changes.

### Is it possible to re-deploy code to an existing address or does it have to be deployed as a new contract?

Yes, this is possible. If a smart contract carries out specific instructions (`set_code()`) its code can be updated and the address will remain the same.
Expand Down
Loading