README.md 12.7 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.com/invite/wGUDt2p
29

Michael Müller's avatar
Michael Müller committed
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 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
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)&nbsp;&nbsp;&nbsp;&nbsp;
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
More relevant links:
Michael Müller's avatar
Michael Müller committed
41
42
* Talk to us on [Element][k2] or in [Discord][l2]
  on the [`ink_smart-contracts`](https://discord.com/channels/722223075629727774/765280480609828864) channel
Michael Müller's avatar
Michael Müller committed
43
44
* [`cargo-contract`](https://github.com/paritytech/cargo-contract) ‒ CLI tool for ink! contracts
* [Canvas UI](https://paritytech.github.io/canvas-ui/#/upload) ‒ Frontend for contract deployment and interaction
45
* [Substrate Contracts Node](https://github.com/paritytech/substrate-contracts-node) ‒ Simple Substrate blockchain which includes smart contract functionality
Michael Müller's avatar
Michael Müller committed
46

47

Michael Müller's avatar
Michael Müller committed
48
## Table of Contents
Hero Bird's avatar
Hero Bird committed
49

Michael Müller's avatar
Michael Müller committed
50
51
52
53
54
55
56
57
58
59
60
61
* [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
62
63


Michael Müller's avatar
Michael Müller committed
64
## Play with It
Michael Müller's avatar
Michael Müller committed
65

66
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
67
68
69
70
71
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).

The [Canvas UI](https://paritytech.github.io/canvas-ui/#/upload) can be used to deploy your contract to a chain and interact with it.

We also have [a demonstration testnet](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fcanvas-rpc.parity.io) running.
Michael Müller's avatar
Michael Müller committed
72
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
73
74


Michael Müller's avatar
Michael Müller committed
75
76
77
## 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).
78

Michael Müller's avatar
Michael Müller committed
79
80
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!:
81

82
```
83
cargo install cargo-contract --force
84
```
85

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

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

90
```
Michael Müller's avatar
Michael Müller committed
91
cargo contract new flipper
92
```
93

Michael Müller's avatar
Michael Müller committed
94
95
96
97
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.
98

Michael Müller's avatar
Michael Müller committed
99
In order to build the contract just execute this command in the `flipper` folder:
100
```
Michael Müller's avatar
Michael Müller committed
101
cargo +nightly contract build
102
```
103

104
105
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.
106
107


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

Michael Müller's avatar
Michael Müller committed
110
111
112
113
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.
114

115

116
Below you can see the code using the `ink_lang` version of ink!.
117
118

```rust
119
use ink_lang as ink;
Hero Bird's avatar
Hero Bird committed
120

121
#[ink::contract]
122
123
124
mod flipper {
    /// The storage of the flipper contract.
    #[ink(storage)]
125
    pub struct Flipper {
126
        /// The single `bool` value.
127
        value: bool,
128
129
    }

130
    impl Flipper {
Michael Müller's avatar
Michael Müller committed
131
132
        /// Instantiates a new Flipper contract and initializes
        /// `value` to `init_value`.
133
        #[ink(constructor)]
134
        pub fn new(init_value: bool) -> Self {
135
136
137
            Self {
                value: init_value,
            }
138
139
        }

140
141
        /// Flips `value` from `true` to `false` or vice versa.
        #[ink(message)]
142
        pub fn flip(&mut self) {
143
            self.value = !self.value;
144
145
146
147
        }

        /// Returns the current state of `value`.
        #[ink(message)]
148
        pub fn get(&self) -> bool {
149
            self.value
150
151
        }
    }
152

Michael Müller's avatar
Michael Müller committed
153
154
    /// Simply execute `cargo test` in order to test your contract
    /// using the below unit tests.
155
156
157
    #[cfg(test)]
    mod tests {
        use super::*;
158
        use ink_lang as ink;
159

160
        #[ink::test]
161
162
163
164
165
166
        fn it_works() {
            let mut flipper = Flipper::new(false);
            assert_eq!(flipper.get(), false);
            flipper.flip();
            assert_eq!(flipper.get(), true);
        }
167
168
    }
}
169
170
```

Michael Müller's avatar
Michael Müller committed
171
172
173
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.
174

Michael Müller's avatar
Michael Müller committed
175
176
177
178
179
180
181
182
183
184
185
186
187
188
## 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:
```
189
cargo contract build
Michael Müller's avatar
Michael Müller committed
190
191
```

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

Michael Müller's avatar
Michael Müller committed
194
For information on how to deploy this to a chain, please have a look at the [Play with It](#play-with-it) section or our [smart contracts workshop](https://substrate.dev/substrate-contracts-workshop/).
Michael Müller's avatar
Michael Müller committed
195
196
197
198


## How it Works

Sacha L's avatar
Sacha L committed
199
* Substrate's [Framework for Runtime Aggregation of Modularised Entities (FRAME)](https://substrate.dev/docs/en/knowledgebase/runtime/frame) contains
200
201
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
202
203
* 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`.
204
Hence ink! contracts are compiled to Wasm.
Michael Müller's avatar
Michael Müller committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
* 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. |
223
224
| `#[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. |
| `#[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
225
| `#[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
226
227
228
229
230

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

231
Use `#[ink::trait_definition]` to define your very own trait definitions that are then implementable by ink! smart contracts.
232
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
233
234
235

### Off-chain Testing

236
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
237
238
239

## Developer Documentation

240
241
242
243
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
244
245
246
247
248
249
250
251
252
| 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
253

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

Michael Müller's avatar
Michael Müller committed
256
257
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
258
259
## License

Michael Müller's avatar
Michael Müller committed
260
261
262
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.