README.md 12.3 KB
Newer Older
Michael Müller's avatar
Michael Müller committed
1
<div align="center">
2
    <img src="./.images/ink-logo-glow.svg" alt="ink!" height="136" />
Michael Müller's avatar
Michael Müller committed
3
4
5
<h1 align="center">
    Parity's ink! for writing smart contracts
</h1>
Hero Bird's avatar
Hero Bird committed
6

Michael Müller's avatar
Michael Müller committed
7
[![linux][a1]][a2] [![codecov][c1]][c2] [![coveralls][d1]][d2] [![loc][e1]][e2] [![matrix][k1]][k2] [![discord][l1]][l2]
8

Andrew Jones's avatar
Andrew Jones committed
9
[a1]: https://gitlab.parity.io/parity/ink/badges/master/pipeline.svg
Hero Bird's avatar
Hero Bird committed
10
[a2]: https://gitlab.parity.io/parity/ink/pipelines?ref=master
11
12
13
14
15
16
[c1]: https://codecov.io/gh/paritytech/ink/branch/master/graph/badge.svg
[c2]: https://codecov.io/gh/paritytech/ink/branch/master
[d1]: https://coveralls.io/repos/github/paritytech/ink/badge.svg?branch=master
[d2]: https://coveralls.io/github/paritytech/ink?branch=master
[e1]: https://tokei.rs/b1/github/paritytech/ink?category=code
[e2]: https://github.com/Aaronepower/tokei#badges
Michael Müller's avatar
Michael Müller committed
17
[f1]: https://img.shields.io/badge/click-blue.svg
18
[f2]: https://paritytech.github.io/ink/ink_storage
Michael Müller's avatar
Michael Müller committed
19
[g1]: https://img.shields.io/badge/click-blue.svg
20
[g2]: https://paritytech.github.io/ink/ink_env
Michael Müller's avatar
Michael Müller committed
21
[i1]: https://img.shields.io/badge/click-blue.svg
22
[i2]: https://paritytech.github.io/ink/ink_prelude
Michael Müller's avatar
Michael Müller committed
23
[j1]: https://img.shields.io/badge/click-blue.svg
Hero Bird's avatar
Hero Bird committed
24
[j2]: https://paritytech.github.io/ink/ink_lang
25
[k1]: https://img.shields.io/badge/matrix-chat-brightgreen.svg?style=flat
Michael Müller's avatar
Michael Müller committed
26
[k2]: https://riot.im/app/#/room/#ink:matrix.parity.io
27
[l1]: https://img.shields.io/discord/722223075629727774?style=flat-square&label=discord
Michael Müller's avatar
Michael Müller committed
28
[l2]: https://discord.gg/ztCASQE
29

30
> <img src="./.images/ink-squid.svg" alt="squink, the ink! mascot" style="vertical-align: middle" align="left" height="60" />ink! is an [eDSL](https://wiki.haskell.org/Embedded_domain_specific_language) to write WebAssembly based smart contracts using the Rust programming language. The compilation target are blockchains built on the [Substrate](https://github.com/paritytech/substrate) framework.
Hero Bird's avatar
Hero Bird committed
31

Michael Müller's avatar
Michael Müller committed
32
<br/>
33

Michael Müller's avatar
Michael Müller committed
34
[Guided Tutorial for Beginners](https://substrate.dev/substrate-contracts-workshop/#/0/building-your-contract)
35
36
37
[ink! Documentation Portal](https://paritytech.github.io/ink-docs)

<br/>
Michael Müller's avatar
Michael Müller committed
38
</div>
Hero Bird's avatar
Hero Bird committed
39

40
41
42
43
44
More relevant links:
* Talk to us on [Element][k2] or [Discord][l2]
* [`cargo-contract`](https://github.com/paritytech/cargo-contract) ‒ cli tool for ink! contracts
* [Canvas UI](https://paritytech.github.io/canvas-ui/#/upload) ‒ webpage for contract deployment and interaction

Michael Müller's avatar
Michael Müller committed
45
## Table of Contents
Hero Bird's avatar
Hero Bird committed
46

Michael Müller's avatar
Michael Müller committed
47
48
49
50
51
52
53
54
55
56
57
58
* [Play with It](#play-with-it)
* [Usage](#usage)
* [Hello, World! ‒ The Flipper](#hello-world--the-flipper)
* [Examples](#examples)
* [How it Works](#how-it-works)
* [ink! Macros & Attributes Overview](#ink-macros--attributes-overview)
  * [Entry Point](#entry-point)
  * [Trait Definitions](#trait-definitions)
  * [Off-chain Testing](#off-chain-testing)
* [Developer Documentation](#developer-documentation)
* [Contributing](#contributing)
* [License](#license)
Michael Müller's avatar
Michael Müller committed
59
60


Michael Müller's avatar
Michael Müller committed
61
## Play with It
Michael Müller's avatar
Michael Müller committed
62

Michael Müller's avatar
Michael Müller committed
63
64
We have [a demonstration testnet](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fcanvas-rpc.parity.io) running.
You can request some tokens to play with from our [Faucet](https://riot.im/app/#/room/#canvas_faucet:matrix.parity.io) and deploy your contracts via the [Canvas UI](https://paritytech.github.io/canvas-ui/#/upload).
Hero Bird's avatar
Hero Bird committed
65

Michael Müller's avatar
Michael Müller committed
66
The [Canvas UI](https://paritytech.github.io/canvas-ui/#/upload) can also be used to deploy your contract to e.g. a Substrate chain which you run locally and execute calls there.
67
68
If you want a quickstart you can use our [canvas-node](https://github.com/paritytech/canvas-node#note) project.
It's a simple Substrate blockchain which is configured to include the Substrate module for smart contract functionality ‒ the `contracts` pallet (see [How it Works](#how-it-works) for more).
Hero Bird's avatar
Hero Bird committed
69

Michael Müller's avatar
Michael Müller committed
70
71
72
## Usage

A prerequisite for compiling smart contracts is to have Rust and Cargo installed. Here's [an installation guide](https://doc.rust-lang.org/cargo/getting-started/installation.html).
73

Michael Müller's avatar
Michael Müller committed
74
We recommend installing [`cargo-contract`](https://github.com/paritytech/cargo-contract), a CLI tool for helping setting up and managing WebAssembly smart contracts written with ink!:
75

76
```
77
cargo install cargo-contract --force
78
```
79

80
81
Use the `--force` to ensure you are updated to the most recent `cargo-contract` version.

Michael Müller's avatar
Michael Müller committed
82
In order to initialize a new ink! project you can use:
Hero Bird's avatar
Hero Bird committed
83

84
```
Michael Müller's avatar
Michael Müller committed
85
cargo contract new flipper
86
```
87

Michael Müller's avatar
Michael Müller committed
88
89
90
91
This will create a folder `flipper` in your work directory.
The folder contains a scaffold `Cargo.toml` and a `lib.rs`, which both contain the necessary building blocks for using ink!.

The `lib.rs` contains our hello world contract ‒ the `Flipper`, which we explain in the next section.
92

93
In order to build the contract just execute these commands in the `flipper` folder:
94
```
95
cargo contract build
96
```
97

98
99
As a result you'll get a file `target/flipper.wasm` file, a `metadata.json` file and a `<contract-name>.contract` file in the `target` folder of your contract.
The `.contract` file combines the Wasm and metadata into one file and needs to be used when deploying the contract.
100
101


Michael Müller's avatar
Michael Müller committed
102
## Hello, World! ‒ The Flipper
Hero Bird's avatar
Hero Bird committed
103

Michael Müller's avatar
Michael Müller committed
104
105
106
107
The `Flipper` contract is a simple contract containing only a single `bool` value.
It provides methods to
* flip its value from `true` to `false` (and vice versa) and
* return the current state.
108

109

110
Below you can see the code using the `ink_lang` version of ink!.
111
112

```rust
113
use ink_lang as ink;
Hero Bird's avatar
Hero Bird committed
114

115
#[ink::contract]
116
117
118
mod flipper {
    /// The storage of the flipper contract.
    #[ink(storage)]
119
    pub struct Flipper {
120
        /// The single `bool` value.
121
        value: bool,
122
123
    }

124
125
126
    impl Flipper {
        /// Instantiates a new Flipper contract and initializes `value` to `init_value`.
        #[ink(constructor)]
127
        pub fn new(init_value: bool) -> Self {
128
129
130
            Self {
                value: init_value,
            }
131
132
        }

133
134
        /// Flips `value` from `true` to `false` or vice versa.
        #[ink(message)]
135
        pub fn flip(&mut self) {
136
            self.value = !self.value;
137
138
139
140
        }

        /// Returns the current state of `value`.
        #[ink(message)]
141
        pub fn get(&self) -> bool {
142
            self.value
143
144
        }
    }
145

146
    /// Simply execute `cargo test` in order to test your contract using the below unit tests.
147
148
149
150
151
152
153
154
155
156
157
    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn it_works() {
            let mut flipper = Flipper::new(false);
            assert_eq!(flipper.get(), false);
            flipper.flip();
            assert_eq!(flipper.get(), true);
        }
158
159
    }
}
160
161
```

162
Place this code in the `./lib.rs` file of your flipper contract and run `cargo contract build` to build your first ink! smart contract example.
163

Michael Müller's avatar
Michael Müller committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
## Examples

In the `examples` folder you'll find a number of examples written in ink!.

Some of the most interesting ones:

* `delegator` ‒ Implements cross-contract calling.
* `trait-erc20` ‒ Defines a trait for `Erc20` contracts and implements it.
* `erc721` ‒ An exemplary implementation of `Erc721` NFT tokens.
* `dns` ‒  A simple `DomainNameService` smart contract.
* …and more, just rummage through the folder 🙃.

To build a single example navigate to the root of the example and run:
```
178
cargo contract build
Michael Müller's avatar
Michael Müller committed
179
180
181
182
183
184
185
186
187
```

You should now have an optimized `<contract-name>.wasm` file and a `metadata.json` file in the `target` folder of the contract.

For further information, please have a look at the [Play with It](#play-with-it) section or our [smart contracts workshop](https://substrate.dev/substrate-contracts-workshop/).


## How it Works

188
189
190
* Substrate's [Framework for Runtime Aggregation of Modularised Entities (FRAME)](https://substrate.dev/docs/en/next/conceptual/runtime/frame) contains
a module  which implements an API for typical functions smart contracts need (storage, querying information about accounts, …).
This module is called the `contracts` pallet,
Michael Müller's avatar
Michael Müller committed
191
192
* The `contracts` pallet requires smart contracts to be uploaded to the blockchain as a Wasm blob.
* ink! is a smart contract language which targets the API exposed by `contracts`.
193
Hence ink! contracts are compiled to Wasm.
Michael Müller's avatar
Michael Müller committed
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
* When executing `cargo contract build` an additional file `metadata.json` is created.
It contains information about e.g. what methods the contract provides for others to call.

## ink! Macros & Attributes Overview

### Entry Point

In a module annotated with `#[ink::contract]` these attributes are available:

| Attribute | Where Applicable | Description |
|:--|:--|:--|
| `#[ink(storage)]` | On `struct` definitions. | Defines the ink! storage struct. There can only be one ink! storage definition per contract. |
| `#[ink(event)]` | On `struct` definitions. | Defines an ink! event. A contract can define multiple such ink! events. |
| `#[ink(anonymous)]` | Applicable to ink! events. | Tells the ink! codegen to treat the ink! event as anonymous which omits the event signature as topic upon emitting. Very similar to anonymous events in Solidity. |
| `#[ink(topic)]` | Applicate on ink! event field. | Tells the ink! codegen to provide a topic hash for the given field. Every ink! event can only have a limited number of such topic field. Similar semantics as to indexed event arguments in Solidity. |
| `#[ink(message)]` | Applicable to methods. | Flags a method for the ink! storage struct as message making it available to the API for calling the contract. |
| `#[ink(constructor)]` | Applicable to method. | Flags a method for the ink! storage struct as constructor making it available to the API for instantiating the contract. |
| `#[ink(payable)]` | Applicable to ink! messages. | Allows receiving value as part of the call of the ink! message. ink! constructors are implicitly payable. |
| `#[ink(selector = "..")]` | Applicable to ink! messages and ink! constructors. | Specifies a concrete dispatch selector for the flagged entity. This allows a contract author to precisely control the selectors of their APIs making it possible to rename their API without breakage. |
| `#[ink(namespace = "..")]` | Applicable to ink! trait implementation blocks. | Changes the resulting selectors of all the ink! messages and ink! constructors within the trait implementation. Allows to disambiguate between trait implementations with overlapping message or constructor names. Use only with great care and consideration! |
Michael Müller's avatar
Michael Müller committed
214
| `#[ink(impl)]` | Applicable to ink! implementation blocks. | Tells the ink! codegen that some implementation block shall be granted access to ink! internals even without it containing any ink! messages or ink! constructors. |
Michael Müller's avatar
Michael Müller committed
215
216
217
218
219
220
221
222
223
224

See [here](https://paritytech.github.io/ink/ink_lang/attr.contract.html) for a more detailed description of those and also for details on the `#[ink::contract]` macro.

### Trait Definitions

Use`#[ink::trait_definition]` to define your very own trait definitions that are then implementable by ink! smart contracts.
See e.g. the [`examples/trait-erc20`](https://github.com/paritytech/ink/blob/master/examples/trait-erc20/lib.rs#L49-L51) contract on how to utilize it or [the documentation](https://paritytech.github.io/ink/ink_lang/attr.trait_definition.html) for details.

### Off-chain Testing

225
The `#[ink::test]` procedural macro enables off-chain testing. See e.g. the [`examples/erc20`](https://github.com/paritytech/ink/blob/master/examples/erc20/lib.rs#L278-L280) contract on how to utilize those or [the documentation](https://paritytech.github.io/ink/ink_lang/attr.test.html) for details.
Michael Müller's avatar
Michael Müller committed
226
227
228

## Developer Documentation

229
230
231
232
We have [a very comprehensive documentation portal](https://paritytech.github.io/ink-docs),
but if you are looking for the crate level documentation itself, then these are
the relevant links:

Michael Müller's avatar
Michael Müller committed
233
234
235
236
237
238
239
240
241
| Crate | Docs | Description |
|:--|:--|:--|
`ink_lang` | [![][j1]][j2] | Language features expose by ink!. See [here](https://paritytech.github.io/ink/ink_lang/attr.contract.html) for a detailed description of attributes which you can use in an `#[ink::contract]`. |
`ink_storage` | [![][f1]][f2] | Data structures available in ink!. |
`ink_env` | [![][g1]][g2] | Low-level interface for interacting with the smart contract Wasm executor. |
`ink_prelude` | [![][i1]][i2] | Common API for no_std and std to access alloc crate types. |


## Contributing
Hero Bird's avatar
Hero Bird committed
242

243
Visit our [contribution guidelines](CONTRIBUTING.md) for more information.
Hero Bird's avatar
Hero Bird committed
244

Michael Müller's avatar
Michael Müller committed
245
246
Use the scripts provided under `scripts/check-*` directory in order to run checks on either the workspace or all examples. Please do this before pushing work in a PR.

Hero Bird's avatar
Hero Bird committed
247
248
## License

249
The entire code within this repository is licensed under the [Apache License 2.0](LICENSE). Please [contact us](https://www.parity.io/contact/) if you have questions about the licensing of our products.