Top Related Projects
Substrate: The platform for blockchain innovators
Polkadot Node Implementation
:chains: A Framework for Building High Value Public Blockchains :sparkles:
Reference client for NEAR Protocol
Web-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.
Hyperledger Fabric is an enterprise-grade permissioned distributed ledger framework for developing solutions and applications. Its modular and versatile design satisfies a broad range of industry use cases. It offers a unique approach to consensus that enables performance at scale while preserving privacy.
Quick Overview
ink is a React-based command-line interface (CLI) framework for building interactive and beautiful command-line apps. It provides a set of customizable components for creating user interfaces in the terminal, allowing developers to leverage their React knowledge to build CLI applications with ease.
Pros
- Familiar React-like syntax and component-based architecture
- Rich set of pre-built components for common CLI elements (text input, select, progress bars, etc.)
- Easy to create visually appealing and interactive terminal applications
- Good documentation and active community support
Cons
- Learning curve for developers not familiar with React
- May be overkill for simple CLI tools
- Performance overhead compared to native CLI applications
- Limited to Node.js environment
Code Examples
- Basic "Hello, World!" example:
import React from 'react';
import {render, Text} from 'ink';
const App = () => <Text>Hello, World!</Text>;
render(<App />);
- Interactive input example:
import React, {useState} from 'react';
import {render, Text, Box, useInput} from 'ink';
const App = () => {
const [name, setName] = useState('');
useInput((input, key) => {
if (key.return) {
// Do something with the input
} else {
setName(prevName => prevName + input);
}
});
return (
<Box>
<Text>Enter your name: {name}</Text>
</Box>
);
};
render(<App />);
- Progress bar example:
import React, {useState, useEffect} from 'react';
import {render, Box} from 'ink';
import Progress from 'ink-progress-bar';
const App = () => {
const [progress, setProgress] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setProgress(prev => (prev < 1 ? prev + 0.1 : 1));
}, 100);
return () => clearInterval(timer);
}, []);
return (
<Box>
<Progress percent={progress} />
</Box>
);
};
render(<App />);
Getting Started
To start using ink, follow these steps:
-
Install ink in your project:
npm install ink react
-
Create a new file (e.g.,
app.js
) and add your ink application code:import React from 'react'; import {render, Text} from 'ink'; const App = () => <Text>Hello from ink!</Text>; render(<App />);
-
Run your application:
node app.js
For more advanced usage and component examples, refer to the official ink documentation.
Competitor Comparisons
Substrate: The platform for blockchain innovators
Pros of Substrate
- More comprehensive blockchain development framework
- Supports multiple programming languages
- Offers greater flexibility and customization options
Cons of Substrate
- Steeper learning curve due to its complexity
- Requires more resources to set up and maintain
Code Comparison
Ink (Smart Contract):
#[ink::contract]
mod erc20 {
#[ink(storage)]
pub struct Erc20 {
total_supply: Balance,
balances: ink::storage::Mapping<AccountId, Balance>,
}
}
Substrate (Runtime Module):
#[frame_support::pallet]
pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn total_supply)]
pub type TotalSupply<T: Config> = StorageValue<_, Balance, ValueQuery>;
#[pallet::storage]
#[pallet::getter(fn balances)]
pub type Balances<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, Balance, ValueQuery>;
}
Ink is specifically designed for writing smart contracts on Substrate-based blockchains, while Substrate is a more extensive framework for building entire blockchain networks. Ink offers a simpler, more focused approach to contract development, making it easier for developers familiar with Rust to get started. Substrate, on the other hand, provides a complete set of tools and modules for creating custom blockchains, offering greater flexibility but requiring more in-depth knowledge of blockchain architecture.
Polkadot Node Implementation
Pros of Polkadot
- Comprehensive blockchain framework for building and connecting custom blockchains
- Robust interoperability features for cross-chain communication
- Advanced governance and consensus mechanisms
Cons of Polkadot
- Steeper learning curve due to complex architecture
- Higher resource requirements for running a node
- Less focused on smart contract development compared to Ink
Code Comparison
Ink (Smart Contract Example):
#[ink::contract]
mod erc20 {
#[ink(storage)]
pub struct Erc20 {
total_supply: Balance,
balances: ink::storage::Mapping<AccountId, Balance>,
}
// ... contract implementation
}
Polkadot (Runtime Module Example):
#[frame_support::pallet]
pub mod pallet {
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
// ... module implementation
}
Summary
Polkadot offers a more comprehensive blockchain ecosystem with advanced features for building and connecting custom blockchains. It excels in interoperability and governance but requires more resources and has a steeper learning curve. Ink, on the other hand, focuses specifically on smart contract development for Substrate-based chains, offering a more streamlined experience for contract-centric projects.
:chains: A Framework for Building High Value Public Blockchains :sparkles:
Pros of Cosmos SDK
- More mature and widely adopted ecosystem with numerous live projects
- Supports multiple programming languages (Go, Rust, JavaScript)
- Offers built-in interoperability features for cross-chain communication
Cons of Cosmos SDK
- Steeper learning curve due to complex architecture
- Requires more resources to run a full node compared to Substrate-based chains
- Less flexibility in customizing core blockchain components
Code Comparison
Cosmos SDK (Go):
type Keeper struct {
storeKey sdk.StoreKey
cdc codec.BinaryCodec
}
func (k Keeper) SetValue(ctx sdk.Context, key string, value string) {
store := ctx.KVStore(k.storeKey)
store.Set([]byte(key), []byte(value))
}
Ink! (Rust):
#[ink(storage)]
pub struct MyContract {
value: HashMap<String, String>,
}
#[ink(message)]
pub fn set_value(&mut self, key: String, value: String) {
self.value.insert(key, value);
}
Both examples show basic key-value storage, but Cosmos SDK uses a more traditional approach with a separate Keeper struct, while Ink! integrates storage directly into the contract struct.
Reference client for NEAR Protocol
Pros of nearcore
- More comprehensive blockchain infrastructure, offering a complete ecosystem for building and deploying decentralized applications
- Higher performance and scalability, designed to handle thousands of transactions per second
- Stronger focus on developer experience with extensive documentation and tooling
Cons of nearcore
- Steeper learning curve due to its more complex architecture and ecosystem
- Less flexibility for customizing the core blockchain functionality compared to ink!'s smart contract approach
- Requires more resources to run and maintain a node
Code Comparison
nearcore (Rust):
impl RuntimeUpgradeChecker for NightshadeRuntime {
fn is_upgrade_required(&self, prev_block_hash: &CryptoHash) -> Result<bool, Error> {
let epoch_id = self.get_epoch_id_from_prev_block(prev_block_hash)?;
Ok(self.is_next_block_epoch_start(prev_block_hash)? && self.will_upgrade_in_next_epoch(&epoch_id)?)
}
}
ink! (Rust):
#[ink(message)]
pub fn transfer(&mut self, to: AccountId, value: Balance) -> Result<()> {
self.transfer_from_to(self.env().caller(), to, value)
}
Web-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.
Pros of Solana
- Higher transaction throughput and lower fees compared to Ink
- More established ecosystem with a larger developer community
- Native support for parallel transaction processing
Cons of Solana
- More complex programming model due to its unique architecture
- Less accessible for developers familiar with Ethereum-like environments
- Steeper learning curve for newcomers to blockchain development
Code Comparison
Solana (Rust):
#[program]
mod hello_world {
use solana_program::entrypoint::ProgramResult;
use solana_program::msg;
pub fn say_hello(ctx: Context<SayHello>) -> ProgramResult {
msg!("Hello, world!");
Ok(())
}
}
Ink (Rust):
#[ink::contract]
mod hello_world {
#[ink(message)]
pub fn say_hello(&self) {
ink_env::debug_println!("Hello, world!");
}
}
Both examples show a simple "Hello, world!" program. Solana uses a more verbose syntax with explicit program structure and result handling, while Ink provides a more concise and declarative approach. Solana's code reflects its focus on performance and parallel execution, whereas Ink's syntax is designed for simplicity and ease of use within the Substrate ecosystem.
Hyperledger Fabric is an enterprise-grade permissioned distributed ledger framework for developing solutions and applications. Its modular and versatile design satisfies a broad range of industry use cases. It offers a unique approach to consensus that enables performance at scale while preserving privacy.
Pros of Fabric
- Enterprise-grade blockchain framework with modular architecture
- Supports multiple programming languages (Go, Java, JavaScript)
- Robust permissioning and privacy features for business use cases
Cons of Fabric
- Steeper learning curve and more complex setup
- Requires more resources to run and maintain
- Less suitable for simple, public blockchain applications
Code Comparison
Fabric (Go):
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, value int) error {
asset := Asset{ID: id, Value: value}
assetJSON, err := json.Marshal(asset)
if err != nil {
return err
}
return ctx.GetStub().PutState(id, assetJSON)
}
Ink (Rust):
#[ink(message)]
pub fn create_asset(&mut self, id: AccountId, value: u32) {
let asset = Asset { id, value };
self.assets.insert(id, asset);
}
Key Differences
- Fabric is a comprehensive blockchain platform, while Ink is a smart contract language for Substrate-based chains
- Fabric supports multiple languages, Ink is Rust-specific
- Fabric offers more built-in enterprise features, Ink focuses on simplicity and WebAssembly compatibility
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Polkadot's ink! for writing smart contracts
ink! is an eDSL to write smart contracts in Rust for blockchains built on the Substrate framework. ink! contracts are compiled to WebAssembly.
Guided Tutorial for Beginners ⢠ink! Documentation Portal ⢠Developer Documentation
More relevant links:
- Substrate Stack Exchange â Forum for getting your ink! questions answered
cargo-contract
â CLI tool for ink! contracts- Contracts UI â Frontend for contract instantiation and interaction
- Substrate Contracts Node â Simple Substrate blockchain which includes smart contract functionality
- Awesome ink! - A curated list of awesome projects for Polkadot's ink!
- We post announcements on Matrix and Discord (in the
ink_smart-contracts
channel).
Table of Contents
- Table of Contents
- Play with It
- Usage
- Hello, World! â The Flipper
- Examples
- How it Works
- ink! Macros & Attributes Overview
- Developer Documentation
- Community Badges
- Contributing
- License
Play with It
The best way to start is to check out the Getting Started page in our documentation.
If you want to have a local setup you can use our substrate-contracts-node
for a quickstart.
It's a simple Substrate blockchain which includes the Substrate module for smart contract functionality â the contracts
pallet (see How it Works for more).
We also have a live testnet named "Contracts" on Rococo. Rococo is a Substrate based parachain which supports ink! smart contracts. For further instructions on using this testnet, follow the instructions in our documentation.
The Contracts UI can be used to instantiate your contract to a chain and interact with it.
Usage
A prerequisite for compiling smart contracts is to have Rust and Cargo installed. Here's an installation guide.
We recommend installing cargo-contract
as well.
It's a CLI tool which helps set up and manage WebAssembly smart contracts written with ink!:
cargo install cargo-contract --force
Use the --force
to ensure you are updated to the most recent cargo-contract
version.
In order to initialize a new ink! project you can use:
cargo contract new flipper
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.
In order to build the contract just execute this command in the flipper
folder:
cargo contract build
As a result you'll get a target/flipper.wasm
file, a flipper.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 instantiating the contract.
Hello, World! â The Flipper
The Flipper
contract is a simple contract containing only a single bool
value.
It provides methods to:
- flip its value from
true
tofalse
(and vice versa) and - return the current state.
Below you can see the code using ink!.
#[ink::contract]
mod flipper {
/// The storage of the flipper contract.
#[ink(storage)]
pub struct Flipper {
/// The single `bool` value.
value: bool,
}
impl Flipper {
/// Instantiates a new Flipper contract and initializes
/// `value` to `init_value`.
#[ink(constructor)]
pub fn new(init_value: bool) -> Self {
Self {
value: init_value,
}
}
/// Flips `value` from `true` to `false` or vice versa.
#[ink(message)]
pub fn flip(&mut self) {
self.value = !self.value;
}
/// Returns the current state of `value`.
#[ink(message)]
pub fn get(&self) -> bool {
self.value
}
}
/// Simply execute `cargo test` in order to test your contract
/// using the below unit tests.
#[cfg(test)]
mod tests {
use super::*;
#[ink::test]
fn it_works() {
let mut flipper = Flipper::new(false);
assert_eq!(flipper.get(), false);
flipper.flip();
assert_eq!(flipper.get(), true);
}
}
}
The flipper/src/lib.rs
file in our examples folder contains exactly this code. Run cargo contract build
to build your
first ink! smart contract.
Examples
In the examples
repository you'll find a number of examples written in ink!.
Some of the most interesting ones:
basic_contract_ref
â Implements cross-contract calling.trait-erc20
â Defines a trait forErc20
contracts and implements it.erc721
â An exemplary implementation ofErc721
NFT tokens.dns
â A simpleDomainNameService
smart contract.- â¦and more, just rummage through the folder ð.
To build a single example navigate to the root of the example and run:
cargo contract build
You should now have an <name>.contract
file in the target
folder of the contract.
For information on how to upload this file to a chain, please have a look at the Play with It section or our smart contracts workshop.
How it Works
- Substrate's Framework for Runtime Aggregation of Modularized Entities (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, - 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
. Hence ink! contracts are compiled to Wasm. - When executing
cargo contract build
an additional file<contract-name>.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(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(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(signature_topic = _)] | Applicable to ink! events. | Specifies custom signature topic of the event that allows to use manually specify shared event definition. |
#[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 fields. Similar semantics as to indexed event arguments in Solidity. |
#[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 = 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(selector = _)] | Applicable to ink! messages. | Specifies a fallback message that is invoked if no other ink! message matches a selector. |
#[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! |
#[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. |
See here 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
contract on how to utilize it or the documentation for details.
Off-chain Testing
The #[ink::test]
procedural macro enables off-chain testing. See e.g. the examples/erc20
contract on how to utilize those or the documentation for details.
Developer Documentation
We have a very comprehensive documentation portal, but if you are looking for the crate level documentation itself, then these are the relevant links:
Crate | Docs | Description |
---|---|---|
ink | Language features exposed by ink!. See here for a detailed description of attributes which you can use in an #[ink::contract] . | |
ink_storage | Data structures available in ink!. | |
ink_env | Low-level interface for interacting with the smart contract Wasm executor. Contains the off-chain testing API as well. | |
ink_prelude | Common API for no_std and std to access alloc crate types. |
Community Badges
Normal Design
[![Built with ink!](https://raw.githubusercontent.com/use-ink/ink/master/.images/badge.svg)](https://github.com/use-ink/ink)
Flat Design
[![Built with ink!](https://raw.githubusercontent.com/use-ink/ink/master/.images/badge_flat.svg)](https://github.com/use-ink/ink)
Contributing
Visit our contribution guidelines for more information.
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.
License
The entire code within this repository is licensed under the Apache License 2.0.
Top Related Projects
Substrate: The platform for blockchain innovators
Polkadot Node Implementation
:chains: A Framework for Building High Value Public Blockchains :sparkles:
Reference client for NEAR Protocol
Web-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.
Hyperledger Fabric is an enterprise-grade permissioned distributed ledger framework for developing solutions and applications. Its modular and versatile design satisfies a broad range of industry use cases. It offers a unique approach to consensus that enables performance at scale while preserving privacy.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot