From 51258208b543b514f03454d54fbc70dae9406173 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Mon, 15 Jan 2024 16:43:29 +0100 Subject: [PATCH 01/18] Delete docs/build/img/swanky/index.md --- docs/build/img/swanky/index.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 docs/build/img/swanky/index.md diff --git a/docs/build/img/swanky/index.md b/docs/build/img/swanky/index.md deleted file mode 100644 index 9daeafb..0000000 --- a/docs/build/img/swanky/index.md +++ /dev/null @@ -1 +0,0 @@ -test From e3192834533beb8e2bf3febd79bd19284af32aac Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:08:20 +0100 Subject: [PATCH 02/18] Add files via upload --- static/docs/build/img/main-page-hero-simple.png | Bin 0 -> 2150 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 static/docs/build/img/main-page-hero-simple.png diff --git a/static/docs/build/img/main-page-hero-simple.png b/static/docs/build/img/main-page-hero-simple.png new file mode 100644 index 0000000000000000000000000000000000000000..4090b99bcc35f8edfab200681aa49e441e349b04 GIT binary patch literal 2150 zcmeAS@N?(olHy`uVBq!ia0y~yU|qn#z{tYE1{ArMG+7x)aTa()7Bet#3xhBt!>l*8o|0J?9FtGpjba4!+V0?SSkdZ+_fI)HVrSIpL zsqW!T+K~QC52&7j;l~>tFwMb{0j7nRq(F2-O9RMa1_i|hj3C-$R2mcvqrozo96;${ tG?$E)4!~qES}KlK7QkdM7%Rym%vU0r7a06G-2*DGJYD@<);T3K0RYo*{BQsO literal 0 HcmV?d00001 From a53a6011b2c8cdcddb5aec32533995e86e679cc9 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:10:58 +0100 Subject: [PATCH 03/18] Update index.scss --- src/pages/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/index.scss b/src/pages/index.scss index 8362490..ba3099b 100644 --- a/src/pages/index.scss +++ b/src/pages/index.scss @@ -5,7 +5,7 @@ text-align: center; position: relative; overflow: hidden; - background-image: url("/static/docs/build/img/mainpageheronew.svg" + background-image: url("/static/docs/build/img/main-page-hero-simple.png" ); @media (min-width: $lg) { padding: 2rem; From cb21221e3ea4c8a87650c8b9e03277f801e0f6a0 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:24:21 +0100 Subject: [PATCH 04/18] Update custom.scss --- src/css/custom.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/css/custom.scss b/src/css/custom.scss index 381057c..fbb26f0 100644 --- a/src/css/custom.scss +++ b/src/css/custom.scss @@ -19,7 +19,7 @@ $astar-blue-dark: #05b6fd; --ifm-code-font-size: 95%; --box-background: #ffffff; --text-color-description: #001f40; - --text-color-title: #0085ff; + --text-color-title: #550CA7; } /* For readability concerns, you should choose a lighter palette in dark mode. */ @@ -52,4 +52,4 @@ $sm: 640px; $md: 768px; $lg: 1024px; $xl: 1280px; -$xxl: 1440px; \ No newline at end of file +$xxl: 1440px; From b6fbf03e2323d1718402a0ce34567d15c8eb6a8e Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:29:17 +0100 Subject: [PATCH 05/18] Delete static/img/docs.svg --- static/img/docs.svg | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 static/img/docs.svg diff --git a/static/img/docs.svg b/static/img/docs.svg deleted file mode 100644 index 29aaa64..0000000 --- a/static/img/docs.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - From 28645d8b1f52dde3f3eca93730fcc506714f2d39 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:29:37 +0100 Subject: [PATCH 06/18] Add files via upload --- static/img/docs.svg | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 static/img/docs.svg diff --git a/static/img/docs.svg b/static/img/docs.svg new file mode 100644 index 0000000..992177a --- /dev/null +++ b/static/img/docs.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From d90319e7bcb0d70f468093e1d4f0cb1164b9960c Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:30:23 +0100 Subject: [PATCH 07/18] Delete static/img/wrench.svg --- static/img/wrench.svg | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 static/img/wrench.svg diff --git a/static/img/wrench.svg b/static/img/wrench.svg deleted file mode 100644 index 5074e60..0000000 --- a/static/img/wrench.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - From 7b9dad1a9926d3ac6aea168cf7cfb75667b6d411 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:30:35 +0100 Subject: [PATCH 08/18] Add files via upload --- static/img/wrench.svg | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 static/img/wrench.svg diff --git a/static/img/wrench.svg b/static/img/wrench.svg new file mode 100644 index 0000000..1e18b8f --- /dev/null +++ b/static/img/wrench.svg @@ -0,0 +1,10 @@ + + + + + + + + + + From dcf2b713c79e0e23ad9182f4088dfd129451cad6 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Fri, 1 Mar 2024 16:44:16 +0100 Subject: [PATCH 09/18] Create _category_.json --- docs/learn/define-events/_category_.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/learn/define-events/_category_.json diff --git a/docs/learn/define-events/_category_.json b/docs/learn/define-events/_category_.json new file mode 100644 index 0000000..bdd3333 --- /dev/null +++ b/docs/learn/define-events/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "How to Define Smart Contract Events", + "position": 5 +} From a850633c79d9f567a98bc3113aafa780b042571b Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Fri, 1 Mar 2024 16:53:44 +0100 Subject: [PATCH 10/18] Create define-events.md --- docs/learn/define-events/define-events.md | 185 ++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 docs/learn/define-events/define-events.md diff --git a/docs/learn/define-events/define-events.md b/docs/learn/define-events/define-events.md new file mode 100644 index 0000000..349b059 --- /dev/null +++ b/docs/learn/define-events/define-events.md @@ -0,0 +1,185 @@ +# Prerequisites + +Before this tutorial, you should have already completed the [Flipper Tutorial](https://docs.astar.network/docs/tutorials/flipper_tutorial). This tutorial targets developers with no experience in ink! and a basic level in Rust. + +## To follow this tutorial you will need: + +- To [set up your ink! environment](https://docs.inkdevhub.io/docs/learn/build-environment/ink_environment) + +## What Will We Be Doing? + +In this tutorial we will implement events, using the most basic contract [Flipper](https://github.com/paritytech/ink/blob/v4.0.0/examples/flipper/lib.rs) as an example. + +## What Will We Use? + +- [ink! 4.2.0](https://github.com/paritytech/ink/tree/v4.2.0) +- [cargo-contract 3.2.0](https://github.com/paritytech/cargo-contract/tree/v3.2.0) +- [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node) + +## What Will You Learn? + +You will learn how to define contract events. + +# Events + +This is a step-by-step explanation of how to implement events in ink! smart contracts. + +## What are Events? + +Smart contract events refer to a feature in blockchain-based smart contracts that allows them to emit signals or notifications when specific conditions are met. Events in smart contracts provide a way for external entities, such as other smart contracts or off-chain applications, to be notified when certain actions or state changes occur within the contract. + +## Types Used in Events + +In Events we can use the same types as in Storage: + +- Rust primitives type + - `bool` + - `u{8,16,32,64,128}` + - `i{8,16,32,64,128}` + - `String` +- Substrate specific types: + - `AccountId` + - `Balance` + - `Hash` +- ink! provided + - `Vec` +- Custom data structure [details](https://use.ink/datastructures/custom-datastructure) + +## Examples + +Let’s take a look at the [Psp22 contract](https://github.com/w3f/PSPs/blob/master/PSPs/psp-22.md). There are two events used in Psp22: + +- Transfer: event emitted when a token transfer occurs. It has 3 arguments: `from`, `to`, and `value`. Where `from`- address of account which sends tokens, `to` - address of account which receives tokens, and `value` is the amount of tokens. +- Approve: event emitted when an approval occurs that `spender` is allowed to withdraw up to the amount of `value` tokens from `owner`. It has 3 arguments: `owner`, `spender`, and `value`. Where `owner`- the address of the account that owns tokens, `sender`- the address of the account that gets an allowance to spend tokens from the `owner`'s account, and `value` is the amount of tokens. + +# How to Define and Use Events? + +Let’s create a learning contract to understand how events work. + +## 1. Flipper Smart Contract + +In a new project folder, execute the following: + +```bash +cargo contract new flipper # flipper is introduced from the beginning. +``` + +## 2. Define an Event + +Let's define an event that will be emitted when the flipper is flipped. Events are just structs with the `#[ink(event)]` attribute and a `#[ink(topic)]` attribute on each field that should be indexed. + +```rust +/// Emitted whenever the stored value changes by a call to the `flip` or `new` methods. +#[ink(event)] +pub struct Flip { + #[ink(topic)] + status: bool, +} +``` + +Then we can emit the event in the `flip` function. + +```rust +pub fn flip(&mut self) { + self.value = !self.value; + + // Emit the `Flip` event. + self.env().emit_event(Flip { + status: self.value, + }); +} +``` + +## 3. Build and Deploy a Contract + +Now, we can compile the contract and deploy it by [Substrate Contracts UI](https://contracts-ui.substrate.io/) to test it. Run the following command to compile the contract: + +```bash +cargo contract build +``` + +Then run your local Substrate node: + +```bash +substrate-contracts-node --dev +``` + +Finally, deploy the contract with [Substrate Contracts UI](https://contracts-ui.substrate.io/). Let's flip the flipper and check the events emitted by the contract. As you can see, the event is emitted when the flipper is flipped and now we have the status `true`. + +We can flip it again and check the events emitted by the contract. As you can see, the event is emitted when the flipper is flipped and now we have the status `false`. + + +## 4. Change event field + +Let's make some changes to the contract and emit another event. Now we will store an integer value in the contract. + +```rust +#[ink(storage)] +pub struct Flipper { + value: i32, +} +``` + +Also, we need to update the `new` function to initialize the `number` field and replace the flip function with a `set` function that will set the value of the `number` field to change `bool` to `i32` in a `get` function. + +```rust +#[ink(constructor)] +pub fn new(init_value: i32) -> Self { + Self { + value: init_value, + } +} + +impl Flipper { + ... + + #[ink(message)] + pub fn set(&mut self, new_value: i32) { + self.value = new_value; + } + + #[ink(message)] + pub fn get(&self) -> i32 { + self.value + } +} +``` + +## 5. Define advanced event + +Let's define an event that will be emitted when the value is set. And we will make it more advanced. + +```rust +#[ink(event)] +pub struct Set { + #[ink(topic)] + old_value: i32, + #[ink(topic)] + new_value: i32, + account: AccountId, +} +``` + +Then we can emit the event in the `set` function. + +```rust +#[ink(message)] +pub fn set(&mut self, new_value: i32) { + let old_value = self.value; + self.value = new_value; + + self.env().emit_event(Set { + old_value, + new_value, + account: self.env().caller(), + }); +} +``` + +This event will be emitted when the value is set. Let's compile the contract and deploy it by [Substrate Contracts UI](https://contracts-ui.substrate.io/) and call the `set` function. + +As you can see, the event is emitted when the value is set and we can see the old value, the new value, and the account that is called the `set` function. + +# Conclusion + +Now you know how to define events in ink! smart contracts. You can check the full code of the contract [here](https://www.notion.so/How-to-define-events-bd4a04049a6a407a8674e33e53e59d57?pvs=21). From 861a9083e60dba0abd89b13b6a0b0ffbc36a7f28 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:04:21 +0100 Subject: [PATCH 11/18] Update define-events.md --- docs/learn/define-events/define-events.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/learn/define-events/define-events.md b/docs/learn/define-events/define-events.md index 349b059..bacced5 100644 --- a/docs/learn/define-events/define-events.md +++ b/docs/learn/define-events/define-events.md @@ -1,4 +1,6 @@ -# Prerequisites +# How to define ink! smart contract events + +## Prerequisites Before this tutorial, you should have already completed the [Flipper Tutorial](https://docs.astar.network/docs/tutorials/flipper_tutorial). This tutorial targets developers with no experience in ink! and a basic level in Rust. From 831998fbc058dd89f98fe710be0bb9da3dbf6c5a Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:06:46 +0100 Subject: [PATCH 12/18] Create define-events.md --- .../tutorials/define-events/define-events.md | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 docs/learn/tutorials/define-events/define-events.md diff --git a/docs/learn/tutorials/define-events/define-events.md b/docs/learn/tutorials/define-events/define-events.md new file mode 100644 index 0000000..bacced5 --- /dev/null +++ b/docs/learn/tutorials/define-events/define-events.md @@ -0,0 +1,187 @@ +# How to define ink! smart contract events + +## Prerequisites + +Before this tutorial, you should have already completed the [Flipper Tutorial](https://docs.astar.network/docs/tutorials/flipper_tutorial). This tutorial targets developers with no experience in ink! and a basic level in Rust. + +## To follow this tutorial you will need: + +- To [set up your ink! environment](https://docs.inkdevhub.io/docs/learn/build-environment/ink_environment) + +## What Will We Be Doing? + +In this tutorial we will implement events, using the most basic contract [Flipper](https://github.com/paritytech/ink/blob/v4.0.0/examples/flipper/lib.rs) as an example. + +## What Will We Use? + +- [ink! 4.2.0](https://github.com/paritytech/ink/tree/v4.2.0) +- [cargo-contract 3.2.0](https://github.com/paritytech/cargo-contract/tree/v3.2.0) +- [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node) + +## What Will You Learn? + +You will learn how to define contract events. + +# Events + +This is a step-by-step explanation of how to implement events in ink! smart contracts. + +## What are Events? + +Smart contract events refer to a feature in blockchain-based smart contracts that allows them to emit signals or notifications when specific conditions are met. Events in smart contracts provide a way for external entities, such as other smart contracts or off-chain applications, to be notified when certain actions or state changes occur within the contract. + +## Types Used in Events + +In Events we can use the same types as in Storage: + +- Rust primitives type + - `bool` + - `u{8,16,32,64,128}` + - `i{8,16,32,64,128}` + - `String` +- Substrate specific types: + - `AccountId` + - `Balance` + - `Hash` +- ink! provided + - `Vec` +- Custom data structure [details](https://use.ink/datastructures/custom-datastructure) + +## Examples + +Let’s take a look at the [Psp22 contract](https://github.com/w3f/PSPs/blob/master/PSPs/psp-22.md). There are two events used in Psp22: + +- Transfer: event emitted when a token transfer occurs. It has 3 arguments: `from`, `to`, and `value`. Where `from`- address of account which sends tokens, `to` - address of account which receives tokens, and `value` is the amount of tokens. +- Approve: event emitted when an approval occurs that `spender` is allowed to withdraw up to the amount of `value` tokens from `owner`. It has 3 arguments: `owner`, `spender`, and `value`. Where `owner`- the address of the account that owns tokens, `sender`- the address of the account that gets an allowance to spend tokens from the `owner`'s account, and `value` is the amount of tokens. + +# How to Define and Use Events? + +Let’s create a learning contract to understand how events work. + +## 1. Flipper Smart Contract + +In a new project folder, execute the following: + +```bash +cargo contract new flipper # flipper is introduced from the beginning. +``` + +## 2. Define an Event + +Let's define an event that will be emitted when the flipper is flipped. Events are just structs with the `#[ink(event)]` attribute and a `#[ink(topic)]` attribute on each field that should be indexed. + +```rust +/// Emitted whenever the stored value changes by a call to the `flip` or `new` methods. +#[ink(event)] +pub struct Flip { + #[ink(topic)] + status: bool, +} +``` + +Then we can emit the event in the `flip` function. + +```rust +pub fn flip(&mut self) { + self.value = !self.value; + + // Emit the `Flip` event. + self.env().emit_event(Flip { + status: self.value, + }); +} +``` + +## 3. Build and Deploy a Contract + +Now, we can compile the contract and deploy it by [Substrate Contracts UI](https://contracts-ui.substrate.io/) to test it. Run the following command to compile the contract: + +```bash +cargo contract build +``` + +Then run your local Substrate node: + +```bash +substrate-contracts-node --dev +``` + +Finally, deploy the contract with [Substrate Contracts UI](https://contracts-ui.substrate.io/). Let's flip the flipper and check the events emitted by the contract. As you can see, the event is emitted when the flipper is flipped and now we have the status `true`. + +We can flip it again and check the events emitted by the contract. As you can see, the event is emitted when the flipper is flipped and now we have the status `false`. + + +## 4. Change event field + +Let's make some changes to the contract and emit another event. Now we will store an integer value in the contract. + +```rust +#[ink(storage)] +pub struct Flipper { + value: i32, +} +``` + +Also, we need to update the `new` function to initialize the `number` field and replace the flip function with a `set` function that will set the value of the `number` field to change `bool` to `i32` in a `get` function. + +```rust +#[ink(constructor)] +pub fn new(init_value: i32) -> Self { + Self { + value: init_value, + } +} + +impl Flipper { + ... + + #[ink(message)] + pub fn set(&mut self, new_value: i32) { + self.value = new_value; + } + + #[ink(message)] + pub fn get(&self) -> i32 { + self.value + } +} +``` + +## 5. Define advanced event + +Let's define an event that will be emitted when the value is set. And we will make it more advanced. + +```rust +#[ink(event)] +pub struct Set { + #[ink(topic)] + old_value: i32, + #[ink(topic)] + new_value: i32, + account: AccountId, +} +``` + +Then we can emit the event in the `set` function. + +```rust +#[ink(message)] +pub fn set(&mut self, new_value: i32) { + let old_value = self.value; + self.value = new_value; + + self.env().emit_event(Set { + old_value, + new_value, + account: self.env().caller(), + }); +} +``` + +This event will be emitted when the value is set. Let's compile the contract and deploy it by [Substrate Contracts UI](https://contracts-ui.substrate.io/) and call the `set` function. + +As you can see, the event is emitted when the value is set and we can see the old value, the new value, and the account that is called the `set` function. + +# Conclusion + +Now you know how to define events in ink! smart contracts. You can check the full code of the contract [here](https://www.notion.so/How-to-define-events-bd4a04049a6a407a8674e33e53e59d57?pvs=21). From 0400ce2fb49d23f67c5e02938823890231716d24 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:08:05 +0100 Subject: [PATCH 13/18] Create _category_.json --- docs/learn/tutorials/define-events/_category_.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/learn/tutorials/define-events/_category_.json diff --git a/docs/learn/tutorials/define-events/_category_.json b/docs/learn/tutorials/define-events/_category_.json new file mode 100644 index 0000000..a880e25 --- /dev/null +++ b/docs/learn/tutorials/define-events/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "ink! Smart Contract Events", + "position": 5 +} From 765156bf669477e12f1993398f6a4d32b5f5da9a Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:10:55 +0100 Subject: [PATCH 14/18] Delete docs/learn/define-events/_category_.json --- docs/learn/define-events/_category_.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 docs/learn/define-events/_category_.json diff --git a/docs/learn/define-events/_category_.json b/docs/learn/define-events/_category_.json deleted file mode 100644 index bdd3333..0000000 --- a/docs/learn/define-events/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "How to Define Smart Contract Events", - "position": 5 -} From 38c06c7641b8d77ea50437a8a15ce70fcfe68a86 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:11:05 +0100 Subject: [PATCH 15/18] Delete docs/learn/define-events/define-events.md --- docs/learn/define-events/define-events.md | 187 ---------------------- 1 file changed, 187 deletions(-) delete mode 100644 docs/learn/define-events/define-events.md diff --git a/docs/learn/define-events/define-events.md b/docs/learn/define-events/define-events.md deleted file mode 100644 index bacced5..0000000 --- a/docs/learn/define-events/define-events.md +++ /dev/null @@ -1,187 +0,0 @@ -# How to define ink! smart contract events - -## Prerequisites - -Before this tutorial, you should have already completed the [Flipper Tutorial](https://docs.astar.network/docs/tutorials/flipper_tutorial). This tutorial targets developers with no experience in ink! and a basic level in Rust. - -## To follow this tutorial you will need: - -- To [set up your ink! environment](https://docs.inkdevhub.io/docs/learn/build-environment/ink_environment) - -## What Will We Be Doing? - -In this tutorial we will implement events, using the most basic contract [Flipper](https://github.com/paritytech/ink/blob/v4.0.0/examples/flipper/lib.rs) as an example. - -## What Will We Use? - -- [ink! 4.2.0](https://github.com/paritytech/ink/tree/v4.2.0) -- [cargo-contract 3.2.0](https://github.com/paritytech/cargo-contract/tree/v3.2.0) -- [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node) - -## What Will You Learn? - -You will learn how to define contract events. - -# Events - -This is a step-by-step explanation of how to implement events in ink! smart contracts. - -## What are Events? - -Smart contract events refer to a feature in blockchain-based smart contracts that allows them to emit signals or notifications when specific conditions are met. Events in smart contracts provide a way for external entities, such as other smart contracts or off-chain applications, to be notified when certain actions or state changes occur within the contract. - -## Types Used in Events - -In Events we can use the same types as in Storage: - -- Rust primitives type - - `bool` - - `u{8,16,32,64,128}` - - `i{8,16,32,64,128}` - - `String` -- Substrate specific types: - - `AccountId` - - `Balance` - - `Hash` -- ink! provided - - `Vec` -- Custom data structure [details](https://use.ink/datastructures/custom-datastructure) - -## Examples - -Let’s take a look at the [Psp22 contract](https://github.com/w3f/PSPs/blob/master/PSPs/psp-22.md). There are two events used in Psp22: - -- Transfer: event emitted when a token transfer occurs. It has 3 arguments: `from`, `to`, and `value`. Where `from`- address of account which sends tokens, `to` - address of account which receives tokens, and `value` is the amount of tokens. -- Approve: event emitted when an approval occurs that `spender` is allowed to withdraw up to the amount of `value` tokens from `owner`. It has 3 arguments: `owner`, `spender`, and `value`. Where `owner`- the address of the account that owns tokens, `sender`- the address of the account that gets an allowance to spend tokens from the `owner`'s account, and `value` is the amount of tokens. - -# How to Define and Use Events? - -Let’s create a learning contract to understand how events work. - -## 1. Flipper Smart Contract - -In a new project folder, execute the following: - -```bash -cargo contract new flipper # flipper is introduced from the beginning. -``` - -## 2. Define an Event - -Let's define an event that will be emitted when the flipper is flipped. Events are just structs with the `#[ink(event)]` attribute and a `#[ink(topic)]` attribute on each field that should be indexed. - -```rust -/// Emitted whenever the stored value changes by a call to the `flip` or `new` methods. -#[ink(event)] -pub struct Flip { - #[ink(topic)] - status: bool, -} -``` - -Then we can emit the event in the `flip` function. - -```rust -pub fn flip(&mut self) { - self.value = !self.value; - - // Emit the `Flip` event. - self.env().emit_event(Flip { - status: self.value, - }); -} -``` - -## 3. Build and Deploy a Contract - -Now, we can compile the contract and deploy it by [Substrate Contracts UI](https://contracts-ui.substrate.io/) to test it. Run the following command to compile the contract: - -```bash -cargo contract build -``` - -Then run your local Substrate node: - -```bash -substrate-contracts-node --dev -``` - -Finally, deploy the contract with [Substrate Contracts UI](https://contracts-ui.substrate.io/). Let's flip the flipper and check the events emitted by the contract. As you can see, the event is emitted when the flipper is flipped and now we have the status `true`. - -We can flip it again and check the events emitted by the contract. As you can see, the event is emitted when the flipper is flipped and now we have the status `false`. - - -## 4. Change event field - -Let's make some changes to the contract and emit another event. Now we will store an integer value in the contract. - -```rust -#[ink(storage)] -pub struct Flipper { - value: i32, -} -``` - -Also, we need to update the `new` function to initialize the `number` field and replace the flip function with a `set` function that will set the value of the `number` field to change `bool` to `i32` in a `get` function. - -```rust -#[ink(constructor)] -pub fn new(init_value: i32) -> Self { - Self { - value: init_value, - } -} - -impl Flipper { - ... - - #[ink(message)] - pub fn set(&mut self, new_value: i32) { - self.value = new_value; - } - - #[ink(message)] - pub fn get(&self) -> i32 { - self.value - } -} -``` - -## 5. Define advanced event - -Let's define an event that will be emitted when the value is set. And we will make it more advanced. - -```rust -#[ink(event)] -pub struct Set { - #[ink(topic)] - old_value: i32, - #[ink(topic)] - new_value: i32, - account: AccountId, -} -``` - -Then we can emit the event in the `set` function. - -```rust -#[ink(message)] -pub fn set(&mut self, new_value: i32) { - let old_value = self.value; - self.value = new_value; - - self.env().emit_event(Set { - old_value, - new_value, - account: self.env().caller(), - }); -} -``` - -This event will be emitted when the value is set. Let's compile the contract and deploy it by [Substrate Contracts UI](https://contracts-ui.substrate.io/) and call the `set` function. - -As you can see, the event is emitted when the value is set and we can see the old value, the new value, and the account that is called the `set` function. - -# Conclusion - -Now you know how to define events in ink! smart contracts. You can check the full code of the contract [here](https://www.notion.so/How-to-define-events-bd4a04049a6a407a8674e33e53e59d57?pvs=21). From 01247c54e92c48eb865060149a2432131441cb1e Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:18:43 +0100 Subject: [PATCH 16/18] Create _category_.json --- docs/learn/tutorials/macros/_category_.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/learn/tutorials/macros/_category_.json diff --git a/docs/learn/tutorials/macros/_category_.json b/docs/learn/tutorials/macros/_category_.json new file mode 100644 index 0000000..e3c26ba --- /dev/null +++ b/docs/learn/tutorials/macros/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "ink! Smart Contract Macros", + "position": 6 +} From 02c71aaed84a1e2e988e5c6245f4f63f99965968 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:35:25 +0100 Subject: [PATCH 17/18] Create macros.md --- docs/learn/tutorials/macros/macros.md | 245 ++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 docs/learn/tutorials/macros/macros.md diff --git a/docs/learn/tutorials/macros/macros.md b/docs/learn/tutorials/macros/macros.md new file mode 100644 index 0000000..ca29983 --- /dev/null +++ b/docs/learn/tutorials/macros/macros.md @@ -0,0 +1,245 @@ +# How to work with ink! smart contract macros + +## Prerequisites + +Before this tutorial, you should have already completed the [Flipper Tutorial](https://docs.astar.network/docs/tutorials/from-zero-to-ink-hero/flipper-contract/). This tutorial targets developers with no experience in ink! and a basic level in Rust. + +### To follow this tutorial you will need: + +- To [set up your ink! environment](https://docs.inkdevhub.io/docs/learn/build-environment/ink_environment) + +### What will we do? + +In this tutorial, we will learn how to use macros provided by ink! + +### What will we use? + +- [ink! 4.2.0](https://github.com/paritytech/ink/tree/v4.2.0) + +## #[ink::contract] + +The `#[ink::contract]` macro is used to initiate the creation of ink! smart contracts. This macro examines the given smart contract code and produces the required code structure. To use it you just need to define a simple rust module with `#[ink::contract]` macro. + +```rust +#[ink::contract] +mod contract { +... +} +``` + +However, in addition to that, every contract must include storage, at least one constructor, and a message. To define storage you can use `[#[ink(storage)]](https://www.notion.so/How-to-work-with-macro-1f6cad316db64eac8539e261d845901f?pvs=21)` macro, to define the constructor and message you need to use `[#[ink(constructor)]](https://www.notion.so/How-to-work-with-macro-1f6cad316db64eac8539e261d845901f?pvs=21)` and `[#[ink(message)]](https://www.notion.so/How-to-work-with-macro-1f6cad316db64eac8539e261d845901f?pvs=21)` macros. + +## #[ink(storage)] + +We have a separate tutorial that explains how to define and use storage. + +## #[ink(constructor)] + +This macro applies to a method that should return the contract object with the initial storage values. + +```rust +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + ... + } + + impl Contract { + #[ink(constructor)] + pub fn new(args...) -> Self { ... } + + #[ink(constructor)] + pub fn another_constructor() -> Self { ... } + + ... + } +} +``` + +The contract may define multiple constructors, allowing users to instantiate it in various ways. + +## #[ink(message)] + +The `#[ink(message)]` attribute is used to flag a method for the ink! storage struct as a message, allowing it to be called by the contract's API. It is important to note that all public functions must use this attribute. At least one method must be defined with `#[ink(message)]`. Methods marked with `#[ink(message)`] are special, because they can be dispatched when the contract is invoked. The ink! messages defined for an ink! smart contract determine its API surface for user interaction. Multiple ink! messages can be defined for an ink! smart contract. An ink! message with a `&self` receiver can only read state, while an ink! message with a `&mut self` receiver can mutate the contract's storage. + +```rust +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + ... + } + + impl Contract { + ... + #[ink(message)] + pub fn can_mutate_storage(&mut self, from: AccountId) { + ... + } + + #[ink(message)] + pub fn can_only_read_storage(&self, from: AccountId) { + ... + } + } +} +``` + +The return value of a message must implement `scale::Encode`. It is important to understand that the collections under `ink_storage`, such as `Vec` or `HashMap`, do not implement `scale::Encode`. This means that you cannot simply return a `Vec` from an ink! message. This restriction is intentional, as returning a complete data structure with potentially unbounded content is an anti-pattern for smart contracts due to unpredictable gas costs. If you truly need to return a data structure in its entirety, then use the ones from `ink_prelude` (for example, `ink_prelude::vec::Vec`), as they implement `scale::Encode`. + +```rust +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + ... + } + + impl Contract { + ... + #[ink(message)] + pub fn can_mutate_storage(&mut self, from: AccountId) { + ... + } + + #[ink(message)] + pub fn can_only_read_storage(&self, from: AccountId) { + ... + } + } +} +``` + +## #[ink(selector = …)] + +By default, ink! creates a selector for each message and constructor, which is necessary for invoking functions in the compiled Wasm blob. The `selector` attribute allows specifying a dispatch selector for the entity, giving control over API selectors and the ability to rename APIs without causing breakage. + +Selectors must be `u32` decodable integers, such as `selector = 0xCAFEBABE` or `selector = 42`. An exception is a fallback selector `_`, which allows contract calls not matching any other message selectors to be dispatched to a fallback message. Fallback messages can be `[payable](https://www.notion.so/How-to-work-with-macro-1f6cad316db64eac8539e261d845901f?pvs=21)`. + +```rust +#[ink(message, selector = 0xABCD123)] +fn message(&self) {} + +#[ink(message, selector = 5552)] +fn another_message(&self) {} + +#[ink(message, payable, selector = _)] +fn fallback(&self) {} +``` + +## #[ink(payable)] + +The ink! message allows receiving value as part of the call. Ink! constructors are implicitly payable due to the initial endowment required by a contract. By default, an ink! message will reject calls that try to add additional funds to the smart contract. However, the authors of ink! smart contracts can make an ink! message payable by adding the `payable` flag to it. It's important to note that ink! constructors are always implicitly payable and thus cannot be flagged as such. + +```rust +#[ink(message, payable)] +pub fn payable_message(&self) { + //stores the amount of token transferred to this message + let transferred_value = self.env().transferred_value(); +} +``` + +## #[ink(default)] + +This feature is applicable to ink! messages and constructors. It serves as a hint for UIs to determine whether a constructor or message should be selected as the default option. Only one constructor or message can be marked as the default. + +```rust +#[ink(constructor, default)] +pub fn default_constructor(&self) { +} + +#[ink(message, default)] +pub fn default_message(&self) { +} +``` + +## #[ink(event)] + +We have a separate tutorial that explains how to define events. You can find it [here](../define-events/define-events.md). + +## #[ink(topic)] + +Fields in ink! events can be designated as topics, prompting the ink! codegen to create a topic hash for the specified field. Each ink! event is limited to a certain number of these topic fields. This functionality is similar to indexed event arguments in Solidity. + +```rust +#[ink(event)] +pub struct Transferred { + #[ink(topic)] + from: Option, + + #[ink(topic)] + to: Option, + + amount: Balance +} +``` + +## #[ink(anonymous)] + +This attribute applies to ink! events and directs the ink! codegen to treat the ink! event as anonymous, excluding the event signature as a topic upon emitting. This behavior closely resembles anonymous events in Solidity. + +In ink!, anonymous events have similar semantics as in Solidity, which means that their event signature will not be included in their event topics serialization, reducing event emitting overhead. This functionality is particularly useful for user-defined events. + +By default, the event signature is one of the topics of the event, unless the event is annotated with `#[ink(anonymous)]`. This attribute implies that it is not possible to filter for specific anonymous events by name. + +```rust +#[ink(event)] +#[ink(anonymous)] +pub struct Event { + #[ink(topic)] + state: StateEnum, + value: i32, +} +``` + +## #[ink(impl)] + +This attribute is designed for a specific scenario that is rarely required. It can be used on ink! implementation blocks to make ink! aware of them. This is particularly useful for implementation blocks that don't contain any other ink! attributes, as they would otherwise be flagged by ink! as a Rust item. By adding `#[ink(impl)]` to such implementation blocks, they are treated as ink! implementation blocks, allowing access to the environment, etc. + +It's important to note that ink! messages and constructors still need to be explicitly flagged as such. + +```rust +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + ... + } + + impl MyStorage { + #[ink(constructor)] + pub fn constructor() -> Self { + ... + } + + #[ink(message)] + pub fn message(&self) { + ... + } + } + + #[ink(impl)] + impl MyStorage { + fn method(&self) -> i32 { + ... + } + } +} +``` + +## #[ink(namespace = "…")] + +Applicable to ink! trait implementation blocks for disambiguating other trait implementation blocks with equal names. This modifies the resulting selectors for all the ink! messages and ink! constructors within the trait implementation, allowing for disambiguation between trait implementations with overlapping messages or constructor names. + +```rust +#[ink(namespace = "namespace_name")] +impl SomeTrait for Contract { + #[ink(message)] + fn message(&self) {} +} +``` + +# Conclusion + +Now you have the knowledge of when and how to use the ink! macros. From 0aa628cbe88cc7d06b78d33138582d1876432524 Mon Sep 17 00:00:00 2001 From: Sofiya <148779211+vsofiya@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:38:32 +0100 Subject: [PATCH 18/18] Create _category_.json --- docs/learn/tutorials/storage/_category_.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/learn/tutorials/storage/_category_.json diff --git a/docs/learn/tutorials/storage/_category_.json b/docs/learn/tutorials/storage/_category_.json new file mode 100644 index 0000000..6976b13 --- /dev/null +++ b/docs/learn/tutorials/storage/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "ink! Smart Contract Macros", + "position": 7 +}