diff --git a/source/mainnet/net/guides/tokens.rst b/source/mainnet/net/guides/tokens.rst
index dc06836126..4621dd6cc3 100644
--- a/source/mainnet/net/guides/tokens.rst
+++ b/source/mainnet/net/guides/tokens.rst
@@ -39,7 +39,7 @@ You can add, inspect, and send tokens in the |bw| and |mw-gen2|.
Once the tokens are added you can see them on the relevant tab.
- An easy way to see how this works is to use the `wCCD example dApp hosted by Concordium `_. Connect it to your |bw| and convert some CCD to wrapped CCD. When you do this, you get the a smart contract index. You can then use this smart contract index to search for tokens on the contract and add them to your |bw|.
+ An easy way to see how this works is to use the `wCCD example dApp hosted by Concordium `_. Connect it to your |bw| and convert some CCD to wrapped CCD. When you do this, you get a smart contract index. You can then use this smart contract index to search for tokens on the contract and add them to your |bw|.
.. dropdown:: Inspect tokens
@@ -108,7 +108,7 @@ You can add, inspect, and send tokens in the |bw| and |mw-gen2|.
Once the tokens are added you can see them on the relevant tab.
- An easy way to see how this works is to use the `wCCD example dApp hosted by Concordium `_. Connect it to your |mw-gen2| and convert some CCD to wrapped CCD. When you do this, you get the a smart contract index. You can then use this smart contract index to search for tokens on the contract and add them to your |mw-gen2|.
+ An easy way to see how this works is to use the `wCCD example dApp hosted by Concordium `_. Connect it to your |mw-gen2| and convert some CCD to wrapped CCD. When you do this, you get a smart contract index. You can then use this smart contract index to search for tokens on the contract and add them to your |mw-gen2|.
.. dropdown:: Inspect tokens
diff --git a/source/mainnet/net/installation/verification-instructions.rst b/source/mainnet/net/installation/verification-instructions.rst
index af566fbc25..70d788b7fb 100644
--- a/source/mainnet/net/installation/verification-instructions.rst
+++ b/source/mainnet/net/installation/verification-instructions.rst
@@ -49,6 +49,9 @@ Linux
.. include:: client-verification-instructions/client-linux.rst
+Cargo Concordium
+================
+
.. _verification-cargo-linux:
Linux
diff --git a/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/testing.rst b/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/testing.rst
index 3daf7e5a85..f53b3370bc 100644
--- a/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/testing.rst
+++ b/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/testing.rst
@@ -83,7 +83,6 @@ Preparation
Before you start, make sure to have the necessary tooling to build Rust
contracts.
The guide :ref:`setup-tools` shows you how to do this.
-Also, make sure to have a text editor setup to write Rust.
Additionally, to run the tests you need to:
diff --git a/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/writing.rst b/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/writing.rst
index 0cedc11e8c..2d2e29f610 100644
--- a/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/writing.rst
+++ b/source/mainnet/smart-contracts-v0/tutorials/piggy-bank/writing.rst
@@ -48,7 +48,6 @@ Preparation
Before you start, make sure to have the necessary tooling to build Rust
contracts.
The guide :ref:`setup-tools` shows you how to do this.
-Also, make sure to have a text editor for writing Rust.
You also need to set up a new smart contract project.
Follow the guide :ref:`setup-contract` and return to this point afterwards.
diff --git a/source/mainnet/smart-contracts/guides/setup-contract.rst b/source/mainnet/smart-contracts/guides/setup-contract.rst
index 0a0e060e53..5b69589b1a 100644
--- a/source/mainnet/smart-contracts/guides/setup-contract.rst
+++ b/source/mainnet/smart-contracts/guides/setup-contract.rst
@@ -11,13 +11,9 @@ The *from a template* option is available for ``cargo-concordium`` version 2.2.0
smart contract templates. Choose the template that best fits your project scope.
The *from scratch* option guides you through the process when you want to start a new project without any boilerplate code.
-.. note::
-
- Concordium recommends that newcomers choose the *from a template* option.
-
.. tabs::
- .. tab:: From a template
+ .. tab:: From a template (recommended)
Concordium maintains several smart contract
`templates `_ (currently a ``default`` template and a ``cis2-nft`` template).
diff --git a/source/mainnet/smart-contracts/tutorials/counter/counter-contract.rst b/source/mainnet/smart-contracts/tutorials/counter/counter-contract.rst
index f6aa70cf3a..b8cc4e60f5 100644
--- a/source/mainnet/smart-contracts/tutorials/counter/counter-contract.rst
+++ b/source/mainnet/smart-contracts/tutorials/counter/counter-contract.rst
@@ -4,18 +4,18 @@
Concordium counter smart contract
=================================
-This tutorial guides you through creating a smart contract using the Concordium a default contract template that simply keeps a counter value in its state. It is a super simple, fundamental example contract that touches on the following points:
+This tutorial guides you through creating a smart contract using the Concordium default contract template that simply keeps a counter value in its state. It is a super simple, fundamental example contract that touches on the following points:
-- to be able to increase/decrease the counter value by the parameter given by the user if it is a positive number
-- view the current value
-- return a custom error when someone tries to increase it with a negative value (or vice versa)
-- all these operations have to be done by only the owner of the contract.
+- Updating the counter value by a parameter given by the user.
+- Reading the current value.
+- Returning a custom error if the counter overflows.
+- Restricting updating the value to only the owner of the contract.
.. Attention::
Before starting the next steps, make sure that you have :ref:`setup the developer environment` with the tools needed.
-Once you have set up the tools needed you are ready to create your smart contract project. First, create a working directory, and run the command below in that directory. It will set up the initial project for you, including necessary rust dependencies.
+Once you have setup your development environment, you are ready to create your smart contract project. Run the initialization command below to create a new working directory for your smart contract. It will set up the initial project for you, including any necessary Rust dependencies.
.. Note::
@@ -25,168 +25,147 @@ Once you have set up the tools needed you are ready to create your smart contrac
$cargo concordium init
-Select the ``default`` option from the menu.
+When prompted for which template to expand, select the ``default`` option. You will then be asked for a name for your project. In this example we'll use "counter", but you can choose whatever name you want.
-.. image:: images/select-default.png
- :width: 100%
+The result is a basic skeleton of a smart contract. Initially, it has a ``State`` struct, an ``init`` function for creating new instances, an ``Error`` enum for custom errors, a ``view`` function to read the state, and a dummy ``receive`` function.
-Then it will ask for a name and a description of your project. Fill them in.
-The result is a basic skeleton of a smart contract.
-Initially, it has a ``State`` struct, an ``init`` function for creating new instances, an ``Error`` enum for custom errors, a ``view`` function, and a ``receive`` function.
-
-.. image:: images/contract.png
- :width: 100%
-
-Add the counter to the state and i8 for integer. Then add the values ``OwnerError``, ``IncrementError``, and ``DecrementError`` to the ``Error`` enum, and specify the counter initial value as zero in the ``init`` function so the counter value starts from 0 when you create a new, fresh instance the contract. Your contract now looks like the example below.
+To build the counter smart contract, rename the ``custom_state_field`` of the ``State`` to ``counter``. Then add the variants ``OwnerError`` and ``OverflowError`` to the ``Error`` enum, and specify the counter initial value as zero in the ``init`` function, so the counter value starts from zero when you create a new, fresh instance of the contract. The first part of your contract now looks like this:
.. code-block:: rust
- /// Your smart contract state.
- #[derive(Serialize, SchemaType, Clone)]
+ /// The state of the smart contract.
+ #[derive(Serialize, SchemaType)]
pub struct State {
- // Your state
counter: i8,
}
- /// Your smart contract errors.
- #[derive(Debug, PartialEq, Eq, Reject, Serial, SchemaType)]
- enum Error {
+ /// Errors that may be emitted by this smart contract.
+ #[derive(Debug, PartialEq, Eq, Reject, Serialize, SchemaType)]
+ pub enum Error {
/// Failed parsing the parameter.
#[from(ParseError)]
- ParseParamsError,
- /// Your error
+ ParseParams,
OwnerError,
- IncrementError,
- DecrementError,
+ OverflowError,
}
- /// Init function that creates a new smart contract.
+ /// Creates a new instance of the smart contract.
#[init(contract = "counter")]
- fn init(
- _ctx: &InitContext,
- _state_builder: &mut StateBuilder,
- ) -> InitResult {
- // Your code
-
+ fn init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult {
Ok(State { counter: 0 })
}
-Increment and decrement counter
-===============================
+Update counter
+==============
-Increment counter
------------------
-
-Then change the update function as described below. Remember that input needs to be parsed without any errors. The value must be positive, otherwise you will get an ``Error::IncrementError``. The transaction must be triggered by the owner of the contract instance or it will throw ``Error::OwnerError``. And the function itself has to be a mutable function because you are going to change the state of the contract.
+Now let's add the function to update the counter. Change the ``receive`` function as shown below. If the input cannot be parsed, we return ``Error::ParseParams``. The function must be triggered by the owner of the contract instance or it will return ``Error::OwnerError``. Note that the ``receive`` attribute on the function includes the ``mutable`` flag, which makes the ``host`` parameter a mutable reference rather than a shared reference, which enables us to change the state of the contract.
.. code-block:: rust
- type IncrementVal = i8;
- /// Receive function. The input parameter is the `IncrementVal`.
- /// If the account owner does not match the contract owner, the receive function will throw [`Error::OwnerError`].
- /// If the number to increment by is not positive or is zero, the receive function will throw [`Error::IncrementError`].
+ /// Updates the smart contracts counter by adding the input to the current value. The input parameter is an `i8`.
+ ///
+ /// If the sender does not match the contract owner, this returns [`Error::OwnerError`] without updating the counter.
+ ///
+ /// If the input failed to parse, this returns [`Error::ParseParams`] without updating the counter.
+ ///
+ /// If the counter would overflow due to the update, the update is not performed and this returns [`Error::OverflowError`].
#[receive(
contract = "counter",
- name = "increment",
- parameter = "IncrementVal",
+ name = "update",
+ parameter = "i8",
error = "Error",
mutable
)]
- fn increment(
- ctx: &ReceiveContext,
- host: &mut Host,
- ) -> Result<(), Error> {
- // Your code
-
- let param: IncrementVal = ctx.parameter_cursor().get()?;
- let state = host.state_mut();
+ fn update(ctx: &ReceiveContext, host: &mut Host) -> Result<(), Error> {
+ // Return Error::OwnerError if the owner does not match the sender.
ensure!(
ctx.sender().matches_account(&ctx.owner()),
Error::OwnerError
);
- ensure!(param > 0, Error::IncrementError);
- state.counter += param;
- Ok(())
- }
-
-Decrement counter
------------------
-
-Add a new mutable function to implement decrement with a similar approach. It will also take an input parameter, but this time make sure that it is negative because a violation will be caused by an ``Error::DecrementError``. Like the other one, this can be triggered by only the owner of the contract,otherwise it will throw an ``Error::OwnerError``.
+ // Returns ParseError on failure.
+ let input: i8 = ctx.parameter_cursor().get()?;
-.. code-block:: rust
-
- #[receive(
- contract = "counter",
- name = "decrement",
- parameter = "IncrementVal",
- error = "Error",
- mutable
- )]
- fn decrement(
- ctx: &ReceiveContext,
- host: &mut Host,
- ) -> Result<(), Error> {
- // Your code
-
- let param: IncrementVal = ctx.parameter_cursor().get()?;
let state = host.state_mut();
- ensure!(
- ctx.sender().matches_account(&ctx.owner()),
- Error::OwnerError
- );
+ let Some(result) = state.counter.checked_add(input) else {
+ return Err(Error::OverflowError);
+ };
- ensure!(param < 0, Error::DecrementError);
- state.counter += param;
+ state.counter = result;
Ok(())
}
View function
-------------
-The view function will return only the counters value so you need to update its return value as i8 and return it from the host.state().
+The view function will return only the counter's value so you need to update its return value as ``i8`` and return it from the ``host.state()``.
.. code-block:: rust
- /// View function that returns the content of the state.
+ /// Returns the state of the smart contract.
#[receive(contract = "counter", name = "view", return_value = "i8")]
- fn view<'a, 'b>(
- _ctx: &'a ReceiveContext,
- host: &'b Host,
- ) -> ReceiveResult {
+ fn view(_ctx: &ReceiveContext, host: &Host) -> ReceiveResult {
Ok(host.state().counter)
}
Build, deploy, and initialize the contract
==========================================
-Create a ``dist`` folder to keep the schema output file and Wasm compiled contract in and run the build command.
+Create a ``dist`` folder for the compiled WASM contract. Then, run the build command.
.. code-block:: console
- $cargo concordium build --out dist/module.wasm.v1 --schema-out dist/schema.bin
+ $cargo concordium build --out dist/module.wasm.v1 --schema-embed
+
+You may get a warning about the build not being verifiable, which you may ignore.
+
+Now we can deploy the smart contract using the Concordium client CLI. If you are running your own node, you can use this command:
-.. image:: images/build.png
- :width: 100%
+.. code-block:: console
+
+ $concordium-client module deploy dist/module.wasm.v1 \
+ --sender \
+ --grpc-port 20001
-Deploy it with the command below.
+Or, if you just want to try things out on testnet, you can use the testing nodes provided by Concordium:
.. code-block:: console
- $concordium-client module deploy dist/module.wasm.v1 --sender --name counter --grpc-port 20001
+ $concordium-client module deploy dist/module.wasm.v1 \
+ --sender \
+ --grpc-ip grpc.testnet.concordium.com \
+ --grpc-port 20000 \
+ --secure
+
+The client may also ask you for the password you specified when you :ref:`imported your key into the Concordium client`. If successful, the command should respond with ``Module successfully deployed with reference: ``, where the module hash is a long hex string. Note down this hash, we'll need it when we initialize a new contract instance below.
-.. image:: images/deploy.png
- :width: 100%
+Note that you will also pay a small fee from your account to pay for the deployment. If you followed the environment setup to create a testnet account, you should already have some CCD for testing purposes in that account.
-Initialize it to create your contract instance, so you are ready to invoke the functions in the next section.
+Finally, let's initialize a contract instance, so you are ready to invoke the contract functions in the next section. Use this command if you are running your own node:
.. code-block:: console
- $concordium-client contract init --sender --energy 30000 --contract counter --grpc-port 20001
+ $concordium-client contract init \
+ --sender \
+ --energy 30000 \
+ --contract counter \
+ --grpc-port 20001
-.. image:: images/initialize.png
- :width: 100%
+Or, use this command to use the Concordium testnet node:
+
+.. code-block:: console
+
+ $concordium-client contract init \
+ --sender \
+ --energy 30000 \
+ --contract counter \
+ --grpc-ip grpc.testnet.concordium.com \
+ --grpc-port 20000 \
+ --secure
+
+Be sure to note down the contract index returned by this command. You'll need the index in the next section to invoke functions for the contract instance.
+
+Congratulations if you made it this far! You have now successfully deployed and initialized a simple smart contract.
Interact with the contract
==========================
@@ -194,46 +173,61 @@ Interact with the contract
View function
-------------
-First, check the initial state of the contract.
+First, check the initial state of the contract. Use this command if you're hosting your own node.
.. code-block:: console
- $concordium-client contract invoke --entrypoint view --schema dist/schema.bin --grpc-port 20001
+ $concordium-client contract invoke \
+ --entrypoint view \
+ --grpc-port 20001
-Since you just initialized the contract it is 0.
+Or, use this command to use the Concordium testnet node:
-.. image:: images/invoke.png
- :width: 100%
+.. code-block:: console
-Increment function
-------------------
+ $concordium-client contract invoke \
+ --entrypoint view \
+ --grpc-ip grpc.testnet.concordium.com \
+ --grpc-port 20000 \
+ --secure
-Create a JSON file that holds your operator that will be given as input to the function and run the command below. Basically, you are saying to the contract instance “with this transaction I will update your state from the increment entrypoint” which is your function name with this parameter.
+Since you just initialized the contract, you should see that the return value is 0.
-.. code-block:: console
+Update function
+---------------
- $concordium-client contract update --entrypoint increment --parameter-json --schema dist/smart-contract-multi/schema.bin --sender --energy 6000 --grpc-port 20001
+In order to call a function that takes input, like our update function, we'll need to create a JSON file that represents the input to the function. Since our input in this simple example is just a number, a simple text file with a number will do, since this is also valid JSON. We can quickly make this file with this command:
-Start by testing with your conditions. First, try another account other than the owner of the contract since you want that only the owner can call this function.
+.. code-block:: console
+
+ echo 42 > input.json
-.. image:: images/owner-error.png
- :width: 100%
+Now we can invoke the update function with that input by using a contract update transaction. This will mutate the smart contract state and store the new value. If you have your own node, you can invoke the update function like so:
-You get error code: -2. Check the developer portal of Concordium for information about :ref:`custom errors`. Basically, -2 means you are calling the second error code from your Error enum, which is OwnerError. So that means you have fulfilled the requirement that only the owner can call these functions. Update the state with number 2 now.
+.. code-block:: console
-.. image:: images/owner-error-ok.png
- :width: 100%
+ $concordium-client contract update \
+ --entrypoint update \
+ --parameter-json input.json \
+ --sender \
+ --energy 6000 \
+ --grpc-port 20001
-Now check the state once more.
+Or, to use Concordium's testnet node, use this command:
-.. image:: images/invoke2.png
- :width: 100%
+.. code-block:: console
-Unsurprisingly, the state is 2. Now check the other requirement: that you cannot increment it with a negative number. Change the value in the JSON file to a negative number like -2.
+ $concordium-client contract update \
+ --entrypoint update \
+ --parameter-json input.json \
+ --sender \
+ --energy 6000 \
+ --grpc-ip grpc.testnet.concordium.com \
+ --grpc-port 20000 \
+ --secure
-.. image:: images/increment-neg-error.png
- :width: 100%
+Now try calling the view function again using the instructions above. If everything worked as it should, you should see the return value is now 42!
-You cannot do it because of error code -3 which is the third element in the enum: ``IncrementError``. That means the increment method operates as expected in your contract.
+We can also test that our error conditions work correctly. For instance, you can try updating the counter using another account (i.e. a different ``--sender`` address). If you try, you'd get an error code of -2. You can check the developer portal for more information about :ref:`custom errors`, but basically, -2 means the second variant from your ``Error`` enum, which is ``OwnerError``, which is what we'd expect.
-You can play with decrement in the same way.
+You can also try updating the counter with a high value that would cause an overflow error, for instance 100 (since 42 + 100 overflows an ``i8``). This should give you a -3 error code, which corresponds to the third variant in the ``Error`` enum, namely ``OverflowError``, just as we would expect.
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/build.png b/source/mainnet/smart-contracts/tutorials/counter/images/build.png
deleted file mode 100644
index ca9a772449..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/build.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/contract.png b/source/mainnet/smart-contracts/tutorials/counter/images/contract.png
deleted file mode 100644
index 285e977e33..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/contract.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/deploy.png b/source/mainnet/smart-contracts/tutorials/counter/images/deploy.png
deleted file mode 100644
index 958c55c562..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/deploy.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/increment-neg-error.png b/source/mainnet/smart-contracts/tutorials/counter/images/increment-neg-error.png
deleted file mode 100644
index 4cacef9f7c..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/increment-neg-error.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/initialize.png b/source/mainnet/smart-contracts/tutorials/counter/images/initialize.png
deleted file mode 100644
index 325ba27c15..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/initialize.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/invoke.png b/source/mainnet/smart-contracts/tutorials/counter/images/invoke.png
deleted file mode 100644
index 69e833b25c..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/invoke.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/invoke2.png b/source/mainnet/smart-contracts/tutorials/counter/images/invoke2.png
deleted file mode 100644
index 1d33869a7b..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/invoke2.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/owner-error-ok.png b/source/mainnet/smart-contracts/tutorials/counter/images/owner-error-ok.png
deleted file mode 100644
index fa0249fc89..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/owner-error-ok.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/owner-error.png b/source/mainnet/smart-contracts/tutorials/counter/images/owner-error.png
deleted file mode 100644
index d3f7147936..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/owner-error.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/counter/images/select-default.png b/source/mainnet/smart-contracts/tutorials/counter/images/select-default.png
deleted file mode 100644
index ef6d4d3e34..0000000000
Binary files a/source/mainnet/smart-contracts/tutorials/counter/images/select-default.png and /dev/null differ
diff --git a/source/mainnet/smart-contracts/tutorials/piggy-bank/deploying.rst b/source/mainnet/smart-contracts/tutorials/piggy-bank/deploying.rst
index 93ac4c1edd..4ebca5a084 100644
--- a/source/mainnet/smart-contracts/tutorials/piggy-bank/deploying.rst
+++ b/source/mainnet/smart-contracts/tutorials/piggy-bank/deploying.rst
@@ -12,12 +12,6 @@ So far you have written and tested a piggy bank smart contract in the Rust_ prog
This part focuses on how you can deploy your developed piggy bank smart contract to the Concordium testnet and interact with it.
-.. warning::
-
- The reader is assumed to have basic knowledge of what a blockchain and smart
- contract is, and some experience with Rust_.
-
-
Preparation
===========
diff --git a/source/mainnet/smart-contracts/tutorials/piggy-bank/index.rst b/source/mainnet/smart-contracts/tutorials/piggy-bank/index.rst
index 27439ef332..5e8cee424e 100644
--- a/source/mainnet/smart-contracts/tutorials/piggy-bank/index.rst
+++ b/source/mainnet/smart-contracts/tutorials/piggy-bank/index.rst
@@ -32,7 +32,8 @@ Finally, the :ref:`fourth part` explains how to set up a we
.. warning::
The reader is assumed to have basic knowledge of what a blockchain and smart
- contracts are, and to have some experience with Rust_.
+ contracts are, and to have some experience with Rust_. Consider reading the
+ simpler :ref:`Counter smart contract tutorial ` first.
Before starting the tutorial, make sure that you have all of the necessary tools installed and running as described in :ref:`Setup the development environment`.
diff --git a/source/mainnet/smart-contracts/tutorials/piggy-bank/testing.rst b/source/mainnet/smart-contracts/tutorials/piggy-bank/testing.rst
index fc2393e61d..2f5efdf8d0 100644
--- a/source/mainnet/smart-contracts/tutorials/piggy-bank/testing.rst
+++ b/source/mainnet/smart-contracts/tutorials/piggy-bank/testing.rst
@@ -95,18 +95,11 @@ This part will focus on how you can write integration-tests for your piggy bank
contract using the |concordium-smart-contract-testing|_ library.
The library simulates part of a blockchain *locally* to allow you to create one or more contracts and interact with them in the tests.
-.. warning::
-
- The reader is assumed to have basic knowledge of what a blockchain and smart
- contract is, and some experience with Rust_.
-
-
Preparation
===========
Before you start, make sure to have the necessary tooling to build Rust
contracts. The guide :ref:`setup-env` shows you how to do this.
-Also, make sure to have a text editor setup to write Rust.
Since you are going to extend the smart contract code written in the :ref:`previous
part`, either follow the previous part or copy the complete
diff --git a/source/mainnet/smart-contracts/tutorials/piggy-bank/writing.rst b/source/mainnet/smart-contracts/tutorials/piggy-bank/writing.rst
index 9e8cd00ced..14b3e10d68 100644
--- a/source/mainnet/smart-contracts/tutorials/piggy-bank/writing.rst
+++ b/source/mainnet/smart-contracts/tutorials/piggy-bank/writing.rst
@@ -31,34 +31,22 @@ This is the first :ref:`part of a tutorial` on smart contract
development. In this part you will focus on how to write a smart contract in the
Rust_ programming language using the |concordium-std| library.
-.. warning::
-
- The reader is assumed to have basic knowledge of what a blockchain and smart
- contract is, and some experience with Rust_.
-
-
Preparation
===========
-Before you start, make sure to have the necessary tooling to build Rust
-contracts. The guide :ref:`setup-env` shows you how to do this.
-Also, make sure to have a text editor for writing Rust.
-
-You also need to set up a new smart contract project.
-Follow the guide :ref:`setup-contract` and return to this point afterwards.
-
-You are now ready to write a smart contract for the Concordium blockchain!
+Set up a new smart contract project by following the guide :ref:`setup-contract` and return to this point afterwards.
Bring in the standard library
=============================
The source code of your smart contract is going to be in the ``src`` directory,
-which already contains the file ``lib.rs``, assuming you follow the above guide
+which already contains a ``lib.rs`` file, assuming you follow the above guide
to set up your project.
-Open ``src/lib.rs`` in your editor and you'll see some code for :ref:`writing tests`,
+
+The smart contract template also includes some example tests under the ``tests`` directory,
which you can delete for now. You will come back to tests later in this tutorial.
-First, bring everything from the |concordium-std|_ library into scope
+In ``lib.rs``, start by bringing everything from the |concordium-std|_ library into scope
by adding the line:
.. code-block:: rust
diff --git a/source/mainnet/smart-contracts/tutorials/voting/index.rst b/source/mainnet/smart-contracts/tutorials/voting/index.rst
index a94e5a574e..d939fd2653 100644
--- a/source/mainnet/smart-contracts/tutorials/voting/index.rst
+++ b/source/mainnet/smart-contracts/tutorials/voting/index.rst
@@ -8,7 +8,7 @@ The Voting dApp
===============
In this tutorial, you are going to get familiar with the deployed voting dApp on testnet. The voting dApp example is intended to show how you can use Concordium to conduct an election using the |bw| to enable users to cast their vote in your election.
-You are going to write a basic web front-end example that can read from and write to the deployed smart contract on testnet.
+You are going to write a basic web frontend example that can read from and write to the deployed smart contract on testnet.
If you want to try this example before starting the tutorial:
@@ -22,15 +22,16 @@ If you want to try this example before starting the tutorial:
#. Click **Vote now**. You can vote and send the link to any other voters. When you click **Cast vote** you must click **Sign & submit** in the |bw|.
-#. Click **Results** to see the election results.
+#. Click **Results** to see the election results. Note that your vote may not appear instantaneously after voting, as the vote transaction waits for confirmation. Give it a few seconds and the vote should appear.
In the :ref:`first part`, you will learn about the voting smart contract.
-In the :ref:`second part`, you will download the |bw| and set up a basic web front-end locally.
+In the :ref:`second part`, you will download the |bw| and set up a basic web frontend locally.
.. warning::
- This tutorial assumes the reader has basic knowledge of what a blockchain and a smart contract is, and some experience with Rust_ and web front-end development.
+ This tutorial assumes the reader has basic knowledge of what a blockchain and a smart contract is, and some experience with Rust_ and web frontend development.
+ Consider reading the simpler :ref:`Counter smart contract tutorial ` first.
To start the tutorial click :ref:`here`.
@@ -39,4 +40,4 @@ To start the tutorial click :ref:`here`.
:maxdepth: 1
Writing a voting smart contract <./voting-sc>
- Setting up the front-end <./voting-dapp>
+ Setting up the frontend <./voting-dapp>
diff --git a/source/mainnet/smart-contracts/tutorials/voting/voting-dapp.rst b/source/mainnet/smart-contracts/tutorials/voting/voting-dapp.rst
index 42efc8567b..77e26fe482 100644
--- a/source/mainnet/smart-contracts/tutorials/voting/voting-dapp.rst
+++ b/source/mainnet/smart-contracts/tutorials/voting/voting-dapp.rst
@@ -2,29 +2,31 @@
.. _voting-frontend:
========================
-Setting up the front end
+Setting up the frontend
========================
-In this part, you will create a web front end. Users can interact with the smart contract more easily
-using a front end compared to interacting with the node directly.
-Non-tech users might find it inconvenient to interact with smart contracts via the Concordium node
+This is the second part of :ref:`the voting smart contract tutorial`. In this part of the tutorial,
+we will create a web frontend application to make it easier for users to interact with the smart contract.
+
+Non-tech users will likely not be able to interact with smart contracts via a Concordium node
and some users may choose not to host their own Concordium node locally. This tutorial part shows you
a setup that eliminates the need for the user to host their own Concordium node.
-You can lower the bar for entry by coding an appealing front end that provides additional information
-to your potential customers. Web front ends are a familiar sight nowadays, but to use
-the front end, users will also need to download a web wallet as a browser extension.
-The installation and safe usage of the |bw| might be new for people using your front end.
+You can lower the bar for entry by coding an appealing frontend that provides additional information
+to your users. Web frontends are a familiar sight nowadays, but to use
+the frontend, users will also need to download the |bw| (or simply "the browser wallet") as a browser extension.
+The installation and safe usage of the browser wallet might be new for people using your frontend.
+
Providing comprehensive explanations and step-by-step guides on your website on topics
-related to the |bw| is important for a good user experience. The |bw|
+related to the browser wallet is important for a good user experience. The browser wallet
connects via `HTTPS `_ to a server that is connected to a Concordium node. This setup alleviates the
need for the user to host their own Concordium node.
.. note::
- Before you start with part 2 of this tutorial, make sure you have:
+ Before you start the second part of this tutorial, make sure you have:
- - access to the a chromium web browser on your computer
+ - Access to a Chromium-based web browser (such as Google Chrome)
- `git `_ installed to be able to clone a repository from `GitHub `_
@@ -37,116 +39,109 @@ need for the user to host their own Concordium node.
|bw|
-------------------------
-A web wallet is a piece of code that can be added as an extension to supported browsers such as ``Chrome``.
-The web wallet allows you to interact with the chain and make transactions.
-Currently, the |bw| does this by connecting to a (gRPC) server that communicates with a node.
-The |bw| hosts the private keys corresponding to the accounts of the user.
+Concordium's browser wallet is an extension to Chromium-based browsers such as Google Chrome.
+The browser wallet allows you to interact with the chain and make transactions, by connecting to a (gRPC) server that communicates with a node.
+The browser wallet hosts the private keys corresponding to the accounts of the user.
-Your front-end code that is run in the browser constructs the transaction object
-and sends it to the |bw|. The transaction object is signed by the private key hosted in the |bw|
-and transmitted to the server via ``HTTPS``. This server has access to a Concordium node and converts
-the request (including the signed transaction object) that comes via ``HTTPS`` from the |bw|
+Your frontend code that is run in the browser constructs the transaction object
+and sends it to the browser wallet extension. The transaction object is signed by the private key hosted in the wallet
+and transmitted to the server via HTTPS. This server has access to a Concordium node and converts
+the request (including the signed transaction object) that comes via HTTPS from the browser wallet
to a request that the Concordium node can execute. The signed transaction is
transmitted via peer-to-peer communication to other Concordium nodes and becomes
part of the Concordium blockchain.
Installation
-^^^^^^^^^^^^
+------------
- You are ready now to install the |bw|. Install the extension for your browser as described :ref:`here`.
+To continue the tutorial, we'll need to install the |bw|. Install the extension for your browser as described :ref:`here`.
- The |bw| connects to a server hosted by Concordium which will take care of the Concordium node on your behalf.
+The wallet connects to a server hosted by Concordium which will take care of the Concordium node on your behalf.
- You are ready now to start the |bw| by clicking on the Concordium icon at the top right of the
- ``Chrome`` browser.
+Start the browser wallet by clicking on the Concordium icon at the top right of the Chrome browser.
- .. image:: ../wCCD/images/wCCD_tutorial_18.png
- :width: 100 %
+.. image:: ../wCCD/images/wCCD_tutorial_18.png
+ :width: 100 %
- .. note::
+.. note::
- The puzzle icon at the top right of the ``Chrome`` browser allows you to manage your browser extensions.
- You can enable pinning of the |bw|.
+ The puzzle icon at the top right of Google Chrome allows you to manage your browser extensions.
+ Here, you can enable pinning of the wallet extension to always have it handy.
- .. image:: ../wCCD/images/wCCD_tutorial_13.png
- :width: 30 %
+ .. image:: ../wCCD/images/wCCD_tutorial_13.png
+ :width: 30 %
- Create a new account on testnet by going through the setup steps of the |bw|.
- You have to choose a password to secure your |bw|.
- This password is needed to log in to your |bw|.
+Create a new account on testnet by going through the setup steps.
+You have to choose a password to secure the wallet.
+This password is needed to log in to the wallet.
- .. image:: ../wCCD/images/wCCD_tutorial_15.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_15.png
+ :width: 30 %
- The |bw| creates a unique secret recovery phrase. Write down the secret recovery phrase
- and keep it in a safe place to be able to recover your accounts in case
- you lose access to your device.
+The wallet creates a unique secret recovery phrase. Write down the secret recovery phrase
+and keep it in a safe place to be able to recover your accounts in case
+you lose access to your device.
- You have completed the setup. Check that your |bw| is connected to the testnet.
+You have now completed the setup. Please verify that your wallet is connected to the Concordium Testnet.
- .. image:: ../wCCD/images/wCCD_tutorial_16.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_16.png
+ :width: 30 %
- .. image:: ../wCCD/images/wCCD_tutorial_17.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_17.png
+ :width: 30 %
- Before you can create a new account. You need to create an identity.
+Before you can create a new account, you need to create an identity. You can do this easily on testnet via the Concordium testnet ID provider.
- .. image:: ../wCCD/images/wCCD_tutorial_19.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_19.png
+ :width: 30 %
- .. image:: ../wCCD/images/wCCD_tutorial_20.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_20.png
+ :width: 30 %
- .. image:: ../wCCD/images/wCCD_tutorial_21.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_21.png
+ :width: 30 %
- .. image:: ../wCCD/images/wCCD_tutorial_22.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_22.png
+ :width: 30 %
- You are ready now to create a new account on testnet.
+Finally, create a new account on testnet.
- .. image:: ../wCCD/images/wCCD_tutorial_19.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_19.png
+ :width: 30 %
- .. image:: ../wCCD/images/wCCD_tutorial_20.png
- :width: 30 %
+.. image:: ../wCCD/images/wCCD_tutorial_20.png
+ :width: 30 %
- You completed the |bw| setup. Send some CCD to your new account or request some CCD from the :ref:`testnet faucet button` within the |bw|.
- Check that your account balance is displayed and you have enough
- CCD to be able to execute transactions.
+For testing you'll need some CCD in your account. Send some CCD to your new account or request some CCD from the :ref:`testnet faucet button` within the wallet.
+Check that your account balance is displayed and you have enough
+CCD to be able to execute transactions.
- .. note::
- You are connected to a website with your |bw| when you see the green ``Connected`` button.
- You can toggle on/off the connection by clicking on the button.
+.. note::
+ The wallet is connected to a website when you see the green ``Connected`` button.
+ You can toggle on/off the connection by clicking on the button.
- .. image:: ../wCCD/images/wCCD_tutorial_14.png
- :width: 40 %
+.. image:: ../wCCD/images/wCCD_tutorial_14.png
+ :width: 40 %
-You can find more information on how to set up the |bw| in :ref:`Setup the Concordium Wallet for web`.
+You can find more information on how to set up the wallet in :ref:`Setup the Concordium Wallet for Web`.
-Running the web front end
+Running the web frontend
-------------------------
You have successfully added the |bw| to your browser in the previous section.
-In the next step of the tutorial, you are going to clone a voting demo front end written with the `React library `_
-and run it locally. The demo front end has the required packages installed to connect to the |bw|
-and implements common flows to deal with the different states that the |bw| could be in. For example,
-the front end will display a ``connect wallet`` button when loading the website. Furthermore, the front end has flows
-to react to the events when the user switches the account in the browser wallet or
-connects/disconnects an account in the |bw| to update the front-end state accordingly.
-
-.. note::
-
- React is a popular open-source front-end JavaScript library.
+In the next step of the tutorial, you are going to clone a voting demo frontend written with the popular frontend framework `React `_
+and run it locally. The demo frontend has the required packages installed to connect to the wallet
+and implements common flows to deal with the different states that the wallet could be in. For example,
+the frontend will display a ``Connect`` button that can be used to connect to the wallet extension. Furthermore, the frontend has flows
+to react to events, such as when the user switches accounts or connects/disconnects an account.
-Clone this `repository `_.
+Clone this `repository `_.
.. code-block:: console
- $git clone https://github.com/Concordium/concordium-browser-wallet/tree/main/examples/voting
+ $git clone https://github.com/Concordium/concordium-browser-wallet
-Build and run the front end as described below:
+Navigate to the ``examples/voting`` subdirectory, then build and run the frontend as described below:
- Run ``yarn`` in the root folder to install all dependencies.
@@ -166,24 +161,24 @@ Build and run the front end as described below:
$cd ./examples/voting/
-- Run ``yarn watch`` to enable hot-reload (useful for development) of the web front end whenever you do any changes to the code.
+- Run ``yarn watch`` to enable hot-reload (useful for development) of the web frontend whenever you do any changes to the code.
.. code-block:: console
$yarn watch
-- Run ``yarn start`` in another terminal to start the web front end.
+- Run ``yarn start`` in another terminal to start the web frontend.
.. code-block:: console
$yarn start
-This command logs a URL in the console (typically http://127.0.0.1:8080). Open this URL in the ``Chrome`` browser.
+The command will log a URL in the console. Open this URL in the Chrome browser.
.. note::
- Check that your |bw| is connected to the testnet and not to mainnet.
+ Make sure that your wallet is connected to testnet and not to mainnet.
-You completed the local front end setup. You are running your own local dApp now. If you want, you can compare it with Concordium's
+You completed the local frontend setup. You are running your own local dApp now. If you want, you can compare it with Concordium's
`voting dApp `_ hosted on testnet. You can use your |bw|
to connect to the dApp.
diff --git a/source/mainnet/smart-contracts/tutorials/voting/voting-sc.rst b/source/mainnet/smart-contracts/tutorials/voting/voting-sc.rst
index 881716d70b..341c0f3c6c 100644
--- a/source/mainnet/smart-contracts/tutorials/voting/voting-sc.rst
+++ b/source/mainnet/smart-contracts/tutorials/voting/voting-sc.rst
@@ -5,36 +5,34 @@
.. _voting-sc:
=========================
-The voting smart contract
+The Voting Smart Contract
=========================
This is the first :ref:`part of a tutorial` on smart contract development. In this part you will focus on how to write a smart contract in the Rust_ programming language using the |concordium-std| library.
-The `voting smart contract `_ allows for conducting an election with several voting options. An `end_time` is set when the election is initialized. Only accounts are eligible to vote. Each account can change its selected voting option as often as it desires until the `end_time` is reached. No voting is possible after the `end_time`.
+The `voting smart contract `_ allows for conducting an election with several voting options. When the election is initialized, a deadline is set, after which no more votes may be cast. Only accounts (not other smart contracts) are eligible to vote. Each account can change its selected voting option as often as it desires until the deadline is reached.
.. warning::
- This contract is not meant for production. It is an example to illustrate how to use the standard library and the tooling Concordium provides. There is no claim that the logic of the contract is reasonable or safe. Do not use these contracts as-is for anything other then experimenting.
+ This contract is not meant for production. It is an example to illustrate how to use the standard library and the tooling Concordium provides. There is no claim that the logic of the contract is reasonable or safe. Do not use these contracts as-is for anything other than experimenting.
Preparation
===========
-Before you start, make sure to have the necessary tooling to build Rust contracts. The guide :ref:`setup-tools` shows you how to do this. Also, make sure to have a text editor for writing Rust.
+Before you start, make sure to have the necessary tooling to build Rust contracts. The guide :ref:`setup-tools` shows you how to do this.
You also need to set up a new smart contract project. Follow the guide :ref:`setup-contract` and return to this point afterwards.
-You are now ready to write a smart contract for the Concordium blockchain!
-
Basic setup
===========
The source code of your smart contract is going to be in the ``src`` directory, which already contains the file ``lib.rs``, assuming you follow the above guide
to set up your project.
-Open ``src/lib.rs`` in your editor and you'll see some code for :ref:`writing tests`,
+The smart contract template also includes some examples tests under the ``tests`` directory,
which you can delete for now. You will come back to tests later in this tutorial.
-First, bring everything from the |concordium-std|_ library into scope by adding the line:
+In the ``lib.rs`` file, start by bringing everything from the |concordium-std|_ library into scope by adding the line:
.. code-block:: rust
@@ -42,42 +40,43 @@ First, bring everything from the |concordium-std|_ library into scope by adding
This library contains everything needed to write a smart contract, such as some parameters, functions, and tests. It provides convenient wrappers around some low-level operations making your code more readable, and although it is not strictly necessary to use this, it will save a lot of code for the vast majority of contract developers.
-The example voting contract allows for the operations:
-
-- `initializing` the election;
-- `view` general information about the election.
-- `vote` for one of the voting options;
-- `getNumberOfVotes` for a requested voting option;
+The voting contract should allow for the following operations:
-A few basic functions are necessary for voting to work.
+- `initializing` the election.
+- `viewing` general information about the election.
+- `voting` for one of the options.
+- `tallying the votes` for a requested voting option.
-- init
-- view
-- vote
-- get_votes
+A few basic functions are necessary for these operations to work:
-``InitParameter`` is called by the ``init`` function. In this example, it contains a description of the election, the voting options, and the end time of the election. Voting options is provided as a vector, however, it is important to remember that there is a limit to the parameter size (65535 bytes), so the size of ``Vec`` is limited.
+- ``init``
+- ``view``
+- ``vote``
+- ``get_votes``
-.. Note::
+Now, let's examine the code in `the example voting smart contract here `_.
- Vec (among other variables) is an input parameter to the `init` function. Since there is a limit to the parameter size (65535 Bytes), the size of the Vec is limited. For more information, see :ref:`Contract instance limits`.
+The ``ElectionConfig`` data structure defines the configuration of the smart contract and is an input to the ``init`` function. In the example code, it contains a description of the election, the voting options, and the deadline of the election. Voting options is provided as a list of strings, however, it is important to remember that there is a limit to the parameter size (65535 bytes), so the maximum size of the list of voting options is large, but limited. For more information, see :ref:`Contract instance limits`.
-``VotingView`` is the return value for the ``view`` function.
+The ``view`` function also returns the ``ElectionConfig`` type, so that users can, for instance, see the available options to vote for.
-In the ``vote`` function, the contract specifies who may vote and when (accounts and before the end time). If a contract tries to vote, an error occurs.
+In the ``vote`` function, the contract specifies who may vote and when (only accounts may vote and only before the deadline). If a contract tries to vote, an error occurs.
-.. code-block:: console
+.. code-block:: rust
let acc = match ctx.sender() {
Address::Account(acc) => acc,
Address::Contract(_) => return Err(VotingError::ContractVoter),
};
-And if the end time has passed, an error occurs.
+And if the deadline has passed, an error occurs.
-.. code-block:: console
+.. code-block:: rust
- ensure!(ctx.metadata().slot_time() <= host.state().end_time, VotingError::VotingFinished);
+ ensure!(
+ ctx.metadata().slot_time() <= host.state().config.deadline,
+ VotingError::VotingFinished
+ );
``get_votes`` gets the number of votes for a specific voting option.
@@ -86,4 +85,24 @@ And if the end time has passed, an error occurs.
Initializing
------------
-The election is open from the point in time that this smart contract is initialized until the `end_time`.
+The election is open from the point in time that this smart contract is initialized until the deadline.
+
+Performance considerations
+--------------------------
+
+An important aspect of the voting smart contract to highlight is the way that votes are tallied.
+
+Note the data duplication in the ``State`` struct. Two ``HashMap``\ s are used: one that maps accounts to the option they voted for,
+and one that maps voting options to the number of votes it has received. However, if you think about it, only the first ``HashMap``,
+the ``ballots`` field is necessary. The tally can of course always be determined by examining the ballots field. This requires looping
+over all ballots, counting how many votes exist for a specific option. However, such a loop would be practically unbounded, as it is only
+limited by the number of votes. Such a loop could exhaust the energy budget of the smart contract functions, potentially making the smart
+contract unusable and vulnerable to a kind of DDoS attack.
+
+Thus, we favor duplicating the data in another ``HashMap`` where the vote count can be retrieved and updated in constant time.
+
+It's important to keep these performance considerations in mind when writing smart contracts. In general, writing smart contracts requires a different methodology than most other usual software development.
+Be sure to think carefully and read up on the common issues and security problems that may occur when you develop smart contracts.
+
+
+In the next part of the tutorial, we will set up a frontend to make it easier to interact with the smart contract.
diff --git a/source/mainnet/smart-contracts/tutorials/wCCD/index.rst b/source/mainnet/smart-contracts/tutorials/wCCD/index.rst
index 6e08a36881..650fd29df8 100644
--- a/source/mainnet/smart-contracts/tutorials/wCCD/index.rst
+++ b/source/mainnet/smart-contracts/tutorials/wCCD/index.rst
@@ -17,9 +17,7 @@ In the :ref:`first part`, you will learn more about the wCCD
In the :ref:`second part`, you will interact with the wCCD token protocol using the ``concordium-client``.
-In the :ref:`third part`, you will download the browser wallet and set up a basic web front end locally.
-
-In the :ref:`fourth part`, you will interact with the wCCD token protocol using your local front end.
+In the :ref:`third part`, you will download the browser wallet and set up a basic web front end locally that you can use to interact with the wCCD token protocol.
.. warning::
@@ -39,4 +37,3 @@ To start the tutorial click :ref:`here`.
Understanding the wCCD token protocol <./wCCD-introduction>
Interacting with the wCCD token protocol <./wCCD-interacting>
Setting up the front end <./wCCD-front-end-set-up>
- Running your first full dApp <./wCCD-full-dApp>
diff --git a/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-front-end-set-up.rst b/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-front-end-set-up.rst
index 9de25d9c41..b78f98e47d 100644
--- a/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-front-end-set-up.rst
+++ b/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-front-end-set-up.rst
@@ -195,6 +195,22 @@ This command logs a URL in the console (typically http://127.0.0.1:8080). Open t
Check that your |bw| is connected to the testnet and not to mainnet.
-You completed the local front end setup.
+Conclusion
+----------
-To continue with the tutorial click :ref:`here`.
+You are now running your own local dApp. If you want, you can compare it with our
+`testnet wCCD dApp `_ hosted on testnet or `mainnet wCCD dApp `_ hosted on mainnet. You can use your |bw|
+to connect to the dApp.
+
+.. note::
+
+ The |bw| is connected to the testnet.
+ You have an identity and account in your wallet loaded.
+ You can find more information on how to set up the wallet in :ref:`Setup the Concordium Wallet for web`.
+
+.. note::
+
+ If you already have an older |bw| extension installed, check its version and download a newer version if applicable.
+ The wCCD front end requires some new features that are supported by the |bw| version 0.8.3 or greater.
+
+Congratulations! You have now completed the wCCD tutorial.
diff --git a/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-full-dApp.rst b/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-full-dApp.rst
deleted file mode 100644
index 15a8a3b76f..0000000000
--- a/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-full-dApp.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-.. include:: ../../../variables.rst
-.. _wCCD-full-dApp:
-
-============================
-Running your first full dApp
-============================
-
-You are running your own local dApp now. If you want, you can compare it with our
-`testnet wCCD dApp `_ hosted on testnet or `mainnet wCCD dApp `_ hosted on mainnet. You can use your |bw|
-to connect to the dApp.
-
-.. note::
-
- The |bw| is connected to the testnet.
- You have an identity and account in your wallet loaded.
- You can find more information on how to set up the |bw| in :ref:`part 3 ` or :ref:`Setup the Concordium Wallet for web`.
-
-.. note::
-
- If you already have an older |bw| extension installed, check its version and download a newer version if applicable.
- The wCCD front end requires some new features that are supported by the |bw| version 0.8.3 or greater.
-
-Congratulations. You have completed the whole wCCD tutorial.
diff --git a/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-interacting.rst b/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-interacting.rst
index b0bf550f9f..1c687b244a 100644
--- a/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-interacting.rst
+++ b/source/mainnet/smart-contracts/tutorials/wCCD/wCCD-interacting.rst
@@ -155,12 +155,6 @@ You are ready now to invoke the ``balanceOf`` function with the following comman
.. image:: ./images/wCCD_tutorial_4.png
:width: 100 %
-.. note::
-
- The smallest unit of CCD is 1 micro CCD and equals 10\ :sup:`−6` (one millionth) of a CCD.
- CCD has 6 decimal places. 1 CCD is represented by the balance
- value of 1,000,000 micro CCD on the blockchain and is worth the equivalent of a balance value of 1,000,000 micro wCCD.
-
.. _operatorOf:
The ``operatorOf`` function
@@ -227,12 +221,12 @@ The ``operatorOf`` function
"Account": [
"4DH219BXocxeVByKpZAGKNAJx7s2w1HFpwaNu1Ljd1mXFXig22"
]
- }
+ },
"owner": {
"Account": [
"4phD1qaS3U1nLrzJcgYyiPq1k8aV1wAjTjYVPE3JaqovViXS4j"
]
- },
+ }
}
]
diff --git a/source/shared/setup-env.rst b/source/shared/setup-env.rst
index d506a95d65..3e5453cdc9 100644
--- a/source/shared/setup-env.rst
+++ b/source/shared/setup-env.rst
@@ -222,6 +222,8 @@ When you export the key it creates a file named ``.export``
.. image:: images/bw-exported-key.png
:width: 100%
+.. _import-client-key:
+
Import the key
--------------