Easy Substrate Smart Contract Deployment Tutorial: Flipper

In this article, we will go through how to deploy basic ink! contract and getting in touch with the stack around Substrate.

What will you learn

You will learn to

  • install prerequisites on your computer,
  • using the ink! cargo-contract plugin to bootstrap a new project
  • building and testing our contract, deploying our contract on a local Substrate node
  • Interacting with our contract using the Polkadot UI Apps.

I made this tutorial working on OSX, but it should work on most popular Linux distributions.

First, we need to get Rust and environment in play

curl https://getsubstrate.io -sSf | bash -s -- --fastrustup target add wasm32-unknown-unknown --toolchain stable
rustup component add rust-src --toolchain nightly
rustup toolchain install nightly-2020-06-01
rustup target add wasm32-unknown-unknown --toolchain nightly-2020-06-01

Then we will need to install the Substrate local node. This would install version 2.0.0-rc4 on your computer. This may take up to 30–40 minutes, depends on the specs of your computer. You may move on to installing ink! CLI meanwhile.

cargo +nightly-2020-06-01 install node-cli --git https://github.com/paritytech/substrate.git --tag v2.0.0-rc4 --force --locked

(Optional) However, if you are in hurry and have docker with you, you can run, or leverage docker-compose I’ve made

docker run -it -p 0.0.0.0:9944:9944 parity/polkadot:latest "--dev"

ink! CLI

To set up the Substrate smart contract project we will need CLI utility which comes with 🔋 batteries included, you can install utility using Cargo:

cargo install cargo-contract --vers 0.6.2 --force

There is a help page if you want to explore other commands

cargo contract --help

Don’t forget, as during writing this manual everything worked with versions cargo-contract-0.6.2 and substrate node v2.0.0-rc4. Substrate ecosystem is under heavy development and may have changed since writing this tutorial.

Creating an ink! project with Flipper

We will now use ink! CLI to generate the file structure we need for Substrate smart contract project. In your working directory run

cargo contract new flipper

It will create a file structure in a folder called a flipper, which we can go explore

cd flipper/
You will see the structure inside the directory like this

Contract Source Code

ink! CLI automatically generates the source code for the Flipper contract, which is about the simplest smart contract you can build.

The Flipper contract is just bool which gets flipped from true to false through the flip() function. You can view the whole source code here.

Testing Your Contract

You will see at the bottom of the source code there is a simple test which verifies the functionality of the contract. We can quickly test that this code is functioning as expected using the off-chain test environment that ink! provides.

cargo +nightly test

You should see successful test completion with passed tests

test result ok!

Now, we can feel confident that things are working, we can actually compile this contract to WASM.

Building Your Contract

To compile your smart contract, run the following command

cargo +nightly contract build
Your Contract is ready

This unique command will turn your ink! project into a WASM binary that you can deploy to your chain. If all goes well, you should see a target the folder which contains this .wasm file.

Contract Metadata

Now we need some contract ABI, we call it metadata

cargo +nightly contract generate-metadata
Your metadata file is ready

We will have a new JSON file metadata.json in the same target directory. We can look at the structure of the file

structure of metadata ABI contract

You can see this file describes all the interfaces that can be used to interact with your contract.

  • registry provides the strings and custom types used throughout the rest of the JSON.
  • Storage defines all the storage items managed by your contract and how to ultimately access them.
  • Contract stores information about the callable functions like constructors and messages a user can call to interact with your contract. It also has helpful information like the events that are emitted by the contract or any docs.

Polkadot JS apps use this file to generate a friendly interface for deploying and interacting with your contract.

While writing this article, there is upcoming version ink! 2.0 support and in future there will be 3.0, so maybe this obsolete tutorial obsolete afterwards as I doubt backward compatibility in Apps, but let me surprise.

Running a Substrate Node

Meanwhile, you should have done installing Substrate node and ready to go launch your local development chain

substrate --dev

You should see something like this. If you run this command in past, I may suggest you run substrate purge-chain --dev to have a fresh environment.

running substrate — dev

Interact with you node

Now you can go to dotapps.io (alternative polkadot.js.org/apps/)

You will see something like this. It’s dashboard apps which help us interact with Substrate and read heavy loads of information it produces and interact back.

Explorer Apps Dashboard

In the dashboard click on the upper left logo and the sidebar with network selector should show up

Pick development — 127.0.0.1:9944

Click on development and choose a local node and click on switch.

Smash that switch button

Important: The UI needs a data type override for v2.0.0-rc4 and older versions. The contracts pallet (SEAL) is getting some breaking changes to adjust it for the next version of ink! Go to Settings > Developer and define the type override.

{   
"ContractExecResult": "ContractExecResultTo255"
}

When you go to Explorer tab of UI, you should also see blocks being produced!

New blocks on your localhost from Substrate

Deploying Your Contract

Now we have generated WASM binary and metadata from our source code and started Substrate node, we want to deploy this contract onto our Substrate blockchain.

Smart contract deployment on Substrate is now a little different than traditional deployment.

Whereas a completely new blob of smart contract source code is deployed each time you push a contract on other platforms, Substrate opts to optimize this behaviour. For example, the standard ERC20 token has been deployed to Ethereum thousands of times, sometimes only with changes to the initial configuration (through the Solidity constructor function). Each of these instances takes up space on the blockchain equivalent to the contract source code size, even though no code was actually changed.

In Substrate, the contract deployment process is split into two halves:

  • Putting your code on the blockchain
  • Creating an instance of your contract

With this pattern, contract code like the ERC20 standard can be put on the blockchain a single time, but instantiated any number of times. No need to continually upload the same source code over and waste space on the blockchain.

Showtime!

Apps have specially designed Contract UI where you can fiddle with your contracts. You can find it under Developer>Contracts.

Then you select Upload WASM

Contracts interface, upload WASM binary

Now it’s time to send your bytes off your disk to the chain. Now we have however the local environment, but later it would be distributed all around other nodes (worldwide).

Click on compiled contract WASM and pick flipper.wasm then you pick contract ABI — metadata we’ve generated (JSON file) and you should see a screen like this.

Yes, you can click Upload and Sign and Submit extrinsic (transaction) a new block is formed and a system event is emitted with contracts.PutCode If the transaction succeeds you will get an system.ExtrinsicSuccess event and your WASM contract will be stored on your Substrate blockchain.

Pick WASM binary and metadata and hit upload

Note: If you get a system.ExtrinsicFailed error message, you may not have allowed enough gas to execute the call. You can verify that this is the cause by looking at the logs in the terminal. This may occur on this or any subsequent contract instantiations or calls.

Ta-Da, it’s there, but not initiated yet!

In Explorer tab, you could notice it’s stored and you will get a hash of the contract.

Yes, this will be in Contracts UI as well

Creating an Instance of Your Contract

Smart contracts exist as an extension of the accounting system on the blockchain. Thus creating an instance of this contract will create a new AccountId which will store any balance managed by the smart contract and allow us to interact with the contract.

In Code tab there is a new object that represents our smart contract. We now need to deploy our smart contract to create an instance.

To instantiate our contract, we just need to give this contract account of endowment (contract rent) of 10 Units in order to pay the storage rent and again set the maximum gas allowed to 1000000

Time to deploy our contract and pay storage rent

Note: As mentioned earlier, contract creation involves creation of a new Account. As such, you must be sure to give the contract account at least the existential deposit defined by your blockchain. We also need to be able to pay the contract’s rent (endowment). If we consume all of this deposit, the contract will become invalid. We can always refill the contract's balance and keep it on chain.

When you hit Deploy, you should see a flurry of events appear including the creation of a new account ( system.NewAccount ) and the instantiation of the contract ( contract.instantiated )

Contract.instantiated, yes!

Calling Your Contract

Now that your contract has been fully deployed, we can start to interact with it! Finally.

Flipper has only two functions, so we will show you what it’s like to play with both of them.

get()

If you take a look back at our contract’s on_deploy() function, we set the initial value of the Flipper contract to false. Let's check that this is the case.

Click on Execute button in Contracts section.

Set the message to send to get() bool , set the maximum gas allowed to 100000. After pressing Call, you should see it returns the value false

Yes, false is what we have expected here

NOTE: You might be wondering: “Why did we need to specify gas when reading a value from a contract?”

If you notice right above the “Call” button is a toggle which allows you to “send call as transaction” or “send as RPC call”. For a read-only request like this, we can simply use an RPC call which will simulate a transaction, but not actually store anything on-chain. Thus, you will still need to specify the right amount of gas to cover your “virtual fee”, but don’t worry, nothing will be charged when making a call this way. :)

flip()

It’s time to flip the value to true now! Notice we are sending this as a transaction, don’t forget to flip toggle.

Send this as transaction to the network

Now we can verify that state by calling get()

We can use here transaction and RPC as well

🔊 Ta-da, you’ve managed to deploy your first smart contract on Substrate with ink!

Contract State Rent

The Substrate contract pallet has a state rent system that forces contracts to stay funded if they want to stay on the blockchain. This means that the more you use a contract, the more fees are taken from it, and at some point, the contract will run out of fees and turn into a non-functioning tombstone. We try to avoid this by giving the contract a large endowment when we initially deploy it. However, if your contract does become a tombstone, for the purposes of this tutorial, the best solution is to just redeploy your contract to the chain.

The best way to prevent this, in general, is to make sure your contract stays well funded. In real-world scenarios, there is a process that you can go through to recover a tombstone contract and get it functioning again, however this is beyond the scope of this tutorial.

Want to continue?

If you are eager to learn more today, follow incrementer template.

Thank you

I would like thank to the perfect support at Substrate Technical (ELEMENT/RIOT) and ink! channel where always nail down issues, even over weekends where you want to crack some code for yourself 💗

About the Author — Matej Nemček 💫🎋

Early in Bitcoin, Ethereum, founder of hackerspace Progressbar

Founder of KodaDot wallet, a reimplementation of original polkadot.js.org from React to VueJS for a broader audience, with the majority in Asia.

Founder of Future Space company without satellites

Bored?

During writing this I’ve listened Symphony №9 from Ludwig Van Beethoven and learning through little about Viennese Music Icon [1] [2] [3] [4] [6] [7]

Source of this tutorial was heavily inspired from Substrate.dev

experimental NFT landscape — https://nft.KodaDot.xyz