From 22fc23ce47ea50cff21673f7383cabfcc017bd9c Mon Sep 17 00:00:00 2001 From: Lyudmil Ivanov <55487633+flmel@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:48:09 +0200 Subject: [PATCH 1/2] chore: update code snippets --- .../2.smart-contracts/release/upgrade.md | 101 ++++++++++++------ 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/docs/2.build/2.smart-contracts/release/upgrade.md b/docs/2.build/2.smart-contracts/release/upgrade.md index b09a56e24d8..28b3db0c8b2 100644 --- a/docs/2.build/2.smart-contracts/release/upgrade.md +++ b/docs/2.build/2.smart-contracts/release/upgrade.md @@ -2,22 +2,28 @@ id: upgrade title: Updating Contracts --- -import {CodeTabs, Language, Github} from "@site/src/components/codetabs"; -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -NEAR accounts separate their logic (contract's code) from their state (storage), allowing the code to be changed. +import {CodeTabs, Language, Github} from "@site/src/components/codetabs"; import +Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; + +NEAR accounts separate their logic (contract's code) from their state (storage), +allowing the code to be changed. Contract's can be updated in two ways: -1. **Through tools** such as [NEAR CLI](../../../4.tools/cli.md) or [near-api-js](../../../4.tools/near-api-js/quick-reference.md) (if you hold the account's [full access key](../../../1.concepts/protocol/access-keys.md)). -2. **Programmatically**, by implementing a method that [takes the new code and deploys it](#programmatic-update). +1. **Through tools** such as [NEAR CLI](../../../4.tools/cli.md) or + [near-api-js](../../../4.tools/near-api-js/quick-reference.md) (if you hold + the account's + [full access key](../../../1.concepts/protocol/access-keys.md)). +2. **Programmatically**, by implementing a method that + [takes the new code and deploys it](#programmatic-update). --- ## Updating Through Tools -Simply re-deploy another contract using your preferred tool, for example, using [NEAR CLI](../../../4.tools/cli.md): +Simply re-deploy another contract using your preferred tool, for example, using +[NEAR CLI](../../../4.tools/cli.md): @@ -49,7 +55,9 @@ near contract deploy use-file without-init-call netw --- ## Programmatic Update + A smart contract can also update itself by implementing a method that: + 1. Takes the new wasm contract as input 2. Creates a Promise to deploy it on itself @@ -94,7 +102,12 @@ near contract call-function as-transaction update_contract fi const code = fs.readFileSync("./path/to/wasm.wasm"); // Call the update_contract method -await wallet.callMethod({contractId: guestBook, method: "update_contract", args: code, gas: "300000000000000"}); +await wallet.callMethod({ + contractId: guestBook, + method: "update_contract", + args: code, + gas: "300000000000000", +}); ``` @@ -103,7 +116,8 @@ await wallet.callMethod({contractId: guestBook, method: "update_contract", args: :::tip DAO Factories -This is how DAO factories [update their contracts](https://github.com/near-daos/sputnik-dao-contract/blob/main/sputnikdao-factory2/src/factory_manager.rs#L60) +This is how DAO factories +[update their contracts](https://github.com/near-daos/sputnik-dao-contract/blob/main/sputnikdao-factory2/src/factory_manager.rs#L60) ::: @@ -111,13 +125,16 @@ This is how DAO factories [update their contracts](https://github.com/near-daos/ ## Migrating the State -Since the account's logic (smart contract) is separated from the account's state (storage), -**the account's state persists** when re-deploying a contract. +Since the account's logic (smart contract) is separated from the account's state +(storage), **the account's state persists** when re-deploying a contract. -Because of this, **adding methods** or **modifying existing ones** will yield **no problems**. +Because of this, **adding methods** or **modifying existing ones** will yield +**no problems**. + +However, deploying a contract that **modifies or removes structures** stored in +the state will raise an error: `Cannot deserialize the contract state`, in which +case you can choose to: -However, deploying a contract that **modifies or removes structures** stored in the state will raise an -error: `Cannot deserialize the contract state`, in which case you can choose to: 1. Use a different account 2. Rollback to the previous contract code 3. Add a method to migrate the contract's state @@ -126,14 +143,17 @@ error: `Cannot deserialize the contract state`, in which case you can choose to: ### The Migration Method -If you have no option but to migrate the state, then you need to implement a method that: +If you have no option but to migrate the state, then you need to implement a +method that: + 1. Reads the current state of the contract 2. Applies different functions to transform it into the new state 3. Returns the new state :::tip DAO Update -This is how DAOs [update themselves](https://github.com/near-daos/sputnik-dao-contract/blob/main/sputnikdao2/src/upgrade.rs#L59) +This is how DAOs +[update themselves](https://github.com/near-daos/sputnik-dao-contract/blob/main/sputnikdao2/src/upgrade.rs#L59) ::: @@ -141,15 +161,16 @@ This is how DAOs [update themselves](https://github.com/near-daos/sputnik-dao-co ### Example: Guest Book Migration -Imagine you have a Guest Book where you store messages, and the users can pay for such messages -to be "premium". You keep track of the messages and payments using the following state: +Imagine you have a Guest Book where you store messages, and the users can pay +for such messages to be "premium". You keep track of the messages and payments +using the following state: + url="https://github.com/near/near-sdk-js/blob/develop/examples/src/basic-updates/basic-updates-base.js" + start="12" end="33" /> @@ -165,15 +186,15 @@ to be "premium". You keep track of the messages and payments using the following #### Update Contract -At some point you realize that you could keep track of the `payments` inside of the `PostedMessage` itself, -so you change the contract to: +At some point you realize that you could keep track of the `payments` inside of +the `PostedMessage` itself, so you change the contract to: + url="https://github.com/near/near-sdk-js/blob/develop/examples/src/basic-updates/basic-updates-update.js" + start="21" end="43" /> @@ -189,22 +210,26 @@ so you change the contract to: #### Incompatible States -If you deploy the update into an initialized account the contract will fail to deserialize the account's state, -because: -1. There is an extra `payments` vector saved in the state (from the previous contract) -2. The stored `PostedMessages` are missing the `payment` field (as in the previous contract) +If you deploy the update into an initialized account the contract will fail to +deserialize the account's state, because: + +1. There is an extra `payments` vector saved in the state (from the previous + contract) +2. The stored `PostedMessages` are missing the `payment` field (as in the + previous contract) #### Migrating the State -To fix the problem, you need to implement a method that goes through the old state, removes the `payments` vector and -adds the information to the `PostedMessages`: +To fix the problem, you need to implement a method that goes through the old +state, removes the `payments` vector and adds the information to the +`PostedMessages`: + url="https://github.com/near/near-sdk-js/blob/develop/examples/src/basic-updates/basic-updates-update.js" + start="5" end="68" /> @@ -218,11 +243,17 @@ adds the information to the `PostedMessages`: -Notice that `migrate` is actually an [initialization method](/build/smart-contracts/anatomy/storage#initializing-the-state) that **ignores** the existing state (`[#init(ignore_state)]`), thus being able to execute and rewrite the state. +Notice that `migrate` is actually an +[initialization method](/build/smart-contracts/anatomy/storage#initializing-the-state) +that **ignores** the existing state (`[#init(ignore_state)]`), thus being able +to execute and rewrite the state. :::tip -You can follow a migration step by step in the [official migration example](https://github.com/near-examples/update-migrate-rust/tree/main/basic-updates/base) -Javascript migration example testfile can be found on here: [test-basic-updates.ava.js](https://github.com/near/near-sdk-js/blob/develop/examples/__tests__/test-basic-updates.ava.js), run by this command: `pnpm run test:basic-update` in examples directory. +You can follow a migration step by step in the +[official migration example](https://github.com/near-examples/update-migrate-rust/tree/main/basic-updates/base) +Javascript migration example testfile can be found on here: +[test-basic-updates.ava.js](https://github.com/near/near-sdk-js/blob/develop/examples/__tests__/test-basic-updates.ava.js), +run by this command: `pnpm run test:basic-update` in examples directory. ::: From 64670aaadc187aba3355eae5a0feddaa29ee3fea Mon Sep 17 00:00:00 2001 From: Lyudmil Ivanov <55487633+flmel@users.noreply.github.com> Date: Thu, 14 Nov 2024 23:07:38 +0200 Subject: [PATCH 2/2] fix: inconsistency in implicit account creation --- docs/1.concepts/protocol/account-id.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/1.concepts/protocol/account-id.md b/docs/1.concepts/protocol/account-id.md index 1c296262239..32b2c6cc18d 100644 --- a/docs/1.concepts/protocol/account-id.md +++ b/docs/1.concepts/protocol/account-id.md @@ -35,7 +35,7 @@ The simplest way to obtain a public / private key that represents an account is ```bash near account create-account fund-later use-auto-generation save-to-folder ~/.near-credentials/implicit -# The file "~/.near-credentials/testnet/8bca86065be487de45e795b2c3154fe834d53ffa07e0a44f29e76a2a5f075df8.json" was saved successfully +# The file "~/.near-credentials/implicit/8bca86065be487de45e795b2c3154fe834d53ffa07e0a44f29e76a2a5f075df8.json" was saved successfully # Here is your console command if you need to script it or re-run: # near account create-account fund-later use-auto-generation save-to-folder ~/.near-credentials/implicit