README.md 13.9 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

7
[![linux][a1]][a2] [![codecov][c1]][c2] [![coveralls][d1]][d2] [![loc][e1]][e2] [![stack-exchange][s1]][s2]
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.com/invite/wGUDt2p
29
30
[s1]: https://img.shields.io/badge/click-white.svg?logo=StackExchange&label=ink!%20Support%20on%20StackExchange&labelColor=white&color=blue
[s2]: https://substrate.stackexchange.com/questions/tagged/ink?tab=Votes
31

Michael Müller's avatar
Michael Müller committed
32
> <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 smart contracts in Rust for blockchains built on the [Substrate](https://github.com/paritytech/substrate) framework. ink! contracts are compiled to WebAssembly.
Hero Bird's avatar
Hero Bird committed
33

Michael Müller's avatar
Michael Müller committed
34
<br/>
35

36
[Guided Tutorial for Beginners](https://docs.substrate.io/tutorials/smart-contracts/)&nbsp;&nbsp;&nbsp;&nbsp;
37
[ink! Documentation Portal](https://ink.substrate.io)&nbsp;&nbsp;&nbsp;&nbsp;
38
39
[Developer Documentation](https://paritytech.github.io/ink/ink_lang/)

40
41

<br/>
Michael Müller's avatar
Michael Müller committed
42
</div>
Hero Bird's avatar
Hero Bird committed
43

44
More relevant links:
45
* [Substrate Stack Exchange](https://substrate.stackexchange.com/questions/tagged/ink?tab=Votes) ‒ Forum for getting your ink! questions answered
Michael Müller's avatar
Michael Müller committed
46
* [`cargo-contract`](https://github.com/paritytech/cargo-contract) ‒ CLI tool for ink! contracts
47
* [Contracts UI](https://contracts-ui.substrate.io/) ‒ Frontend for contract instantiation and interaction
48
* [Substrate Contracts Node](https://github.com/paritytech/substrate-contracts-node) ‒ Simple Substrate blockchain which includes smart contract functionality
49
50
* We post announcements on [Matrix][k2] and [Discord][l2] (in the
  [`ink_smart-contracts`](https://discord.com/channels/722223075629727774/765280480609828864) channel).
Michael Müller's avatar
Michael Müller committed
51

52

Michael Müller's avatar
Michael Müller committed
53
## Table of Contents
Hero Bird's avatar
Hero Bird committed
54

Michael Müller's avatar
Michael Müller committed
55
56
57
58
59
60
61
62
63
64
* [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)
65
* [Community Badges](#community-badges)
Michael Müller's avatar
Michael Müller committed
66
67
* [Contributing](#contributing)
* [License](#license)
Michael Müller's avatar
Michael Müller committed
68
69


Michael Müller's avatar
Michael Müller committed
70
## Play with It
Michael Müller's avatar
Michael Müller committed
71

72
If you want to have a local setup you can use our [`substrate-contracts-node`](https://github.com/paritytech/substrate-contracts-node) for a quickstart.
Michael Müller's avatar
Michael Müller committed
73
74
It's a simple Substrate blockchain which includes the Substrate module for smart contract functionality ‒ the `contracts` pallet (see [How it Works](#how-it-works) for more).

75
We also have a live testnet on [Rococo](https://github.com/paritytech/cumulus/#rococo-)
76
called [Canvas](https://ink.substrate.io/canvas). Canvas is a Substrate based
77
78
parachain which supports ink! smart contracts. For further instructions on using this
testnet, follow the instructions in the
79
[our documentation](https://ink.substrate.io/canvas#rococo-deployment).
80

81
For both types of chains the [Contracts UI](https://contracts-ui.substrate.io/)
82
can be used to instantiate your contract to a chain and interact with it.
Hero Bird's avatar
Hero Bird committed
83

Michael Müller's avatar
Michael Müller committed
84
85
86
## 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).
87

Michael Müller's avatar
Michael Müller committed
88
89
We recommend installing [`cargo-contract`](https://github.com/paritytech/cargo-contract) as well.
It's a CLI tool which helps set up and manage WebAssembly smart contracts written with ink!:
90

91
```
92
cargo install cargo-contract --force
93
```
94

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

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

99
```
Michael Müller's avatar
Michael Müller committed
100
cargo contract new flipper
101
```
102

Michael Müller's avatar
Michael Müller committed
103
104
105
106
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.
107

Michael Müller's avatar
Michael Müller committed
108
In order to build the contract just execute this command in the `flipper` folder:
109
```
Michael Müller's avatar
Michael Müller committed
110
cargo +nightly contract build
111
```
112

113
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.
114
The `.contract` file combines the Wasm and metadata into one file and needs to be used when instantiating the contract.
115
116


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

Michael Müller's avatar
Michael Müller committed
119
120
121
122
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.
123

124

125
Below you can see the code using the `ink_lang` version of ink!.
126
127

```rust
128
use ink_lang as ink;
Hero Bird's avatar
Hero Bird committed
129

130
#[ink::contract]
131
132
133
mod flipper {
    /// The storage of the flipper contract.
    #[ink(storage)]
134
    pub struct Flipper {
135
        /// The single `bool` value.
136
        value: bool,
137
138
    }

139
    impl Flipper {
Michael Müller's avatar
Michael Müller committed
140
141
        /// Instantiates a new Flipper contract and initializes
        /// `value` to `init_value`.
142
        #[ink(constructor)]
143
        pub fn new(init_value: bool) -> Self {
144
145
146
            Self {
                value: init_value,
            }
147
148
        }

149
150
        /// Flips `value` from `true` to `false` or vice versa.
        #[ink(message)]
151
        pub fn flip(&mut self) {
152
            self.value = !self.value;
153
154
155
156
        }

        /// Returns the current state of `value`.
        #[ink(message)]
157
        pub fn get(&self) -> bool {
158
            self.value
159
160
        }
    }
161

Michael Müller's avatar
Michael Müller committed
162
163
    /// Simply execute `cargo test` in order to test your contract
    /// using the below unit tests.
164
165
166
    #[cfg(test)]
    mod tests {
        use super::*;
167
        use ink_lang as ink;
168

169
        #[ink::test]
170
171
172
173
174
175
        fn it_works() {
            let mut flipper = Flipper::new(false);
            assert_eq!(flipper.get(), false);
            flipper.flip();
            assert_eq!(flipper.get(), true);
        }
176
177
    }
}
178
179
```

Michael Müller's avatar
Michael Müller committed
180
181
182
The [`flipper/src/lib.rs`](https://github.com/paritytech/ink/blob/master/examples/flipper/lib.rs)
file in our examples folder contains exactly this code. Run `cargo contract build` to build your
first ink! smart contract.
183

Michael Müller's avatar
Michael Müller committed
184
185
186
187
188
189
190
191
192
193
194
195
196
197
## 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:
```
198
cargo contract build
Michael Müller's avatar
Michael Müller committed
199
200
```

Michael Müller's avatar
Michael Müller committed
201
You should now have an `<name>.contract` file in the `target` folder of the contract.
Michael Müller's avatar
Michael Müller committed
202

203
For information on how to upload this file to a chain, please have a look at the [Play with It](#play-with-it) section or our [smart contracts workshop](https://docs.substrate.io/tutorials/v3/ink-workshop/pt1).
Michael Müller's avatar
Michael Müller committed
204
205
206
207


## How it Works

Dan Shields's avatar
Dan Shields committed
208
209
* Substrate's [Framework for Runtime Aggregation of Modularized Entities (FRAME)](https://docs.substrate.io/v3/runtime/frame)
contains a module  which implements an API for typical functions smart contracts need (storage,querying information about accounts, …).
210
This module is called the `contracts` pallet,
Michael Müller's avatar
Michael Müller committed
211
212
* 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`.
213
Hence ink! contracts are compiled to Wasm.
Michael Müller's avatar
Michael Müller committed
214
215
216
217
218
219
220
221
222
223
224
225
* 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. |
226
227
| `#[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. |
Michael Müller's avatar
Michael Müller committed
228
229
| `#[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. |
Dan Shields's avatar
Dan Shields committed
230
| `#[ink(topic)]` | Applicable 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. |
Michael Müller's avatar
Michael Müller committed
231
| `#[ink(payable)]` | Applicable to ink! messages. | Allows receiving value as part of the call of the ink! message. ink! constructors are implicitly payable. |
232
| `#[ink(selector = S:u32)]` | 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. |
233
| `#[ink(selector = _)]` | Applicable to ink! messages. | Specifies a fallback message that is invoked if no other ink! message matches a selector. |
234
| `#[ink(namespace = N:string)]` | 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
235
| `#[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
236
237
238
239
240

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

241
Use `#[ink::trait_definition]` to define your very own trait definitions that are then implementable by ink! smart contracts.
242
See e.g. the [`examples/trait-erc20`](https://github.com/paritytech/ink/blob/v3.0.0-rc5/examples/trait-erc20/lib.rs#L35-L37) contract on how to utilize it or [the documentation](https://paritytech.github.io/ink/ink_lang/attr.trait_definition.html) for details.
Michael Müller's avatar
Michael Müller committed
243
244
245

### Off-chain Testing

246
The `#[ink::test]` procedural macro enables off-chain testing. See e.g. the [`examples/erc20`](https://github.com/paritytech/ink/blob/v3.0.0-rc5/examples/erc20/lib.rs#L248-L250) 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
247
248
249

## Developer Documentation

250
We have [a very comprehensive documentation portal](https://ink.substrate.io),
251
252
253
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
254
255
| Crate | Docs | Description |
|:--|:--|:--|
Michael Müller's avatar
Michael Müller committed
256
`ink_lang` | [![][j1]][j2] | Language features exposed 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]`. |
Michael Müller's avatar
Michael Müller committed
257
`ink_storage` | [![][f1]][f2] | Data structures available in ink!. |
Michael Müller's avatar
Michael Müller committed
258
`ink_env` | [![][g1]][g2] | Low-level interface for interacting with the smart contract Wasm executor. Contains [the off-chain testing API](https://paritytech.github.io/ink/ink_env/test/index.html) as well. |
Michael Müller's avatar
Michael Müller committed
259
260
`ink_prelude` | [![][i1]][i2] | Common API for no_std and std to access alloc crate types. |

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
## Community Badges

### Normal Design

[![Built with ink!](.images/badge.svg)](https://github.com/paritytech/ink)

```markdown
[![Built with ink!](https://raw.githubusercontent.com/paritytech/ink/master/.images/badge.svg)](https://github.com/paritytech/ink)
```

### Flat Design

[![Built with ink!](.images/badge_flat.svg)](https://github.com/paritytech/ink)

```markdown
[![Built with ink!](https://raw.githubusercontent.com/paritytech/ink/master/.images/badge_flat.svg)](https://github.com/paritytech/ink)
```
Michael Müller's avatar
Michael Müller committed
278
279

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

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

Michael Müller's avatar
Michael Müller committed
283
284
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
285
286
## License

Michael Müller's avatar
Michael Müller committed
287
288
289
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.