Smart Contract Runtime Environment
Astar & Shiden runtimes are based on Substrate. Both networks incorporate
pallet-contracts to enable Wasm smart-contract capabilities. The
pallet-contracts is a sandbox environment to deploy and execute WebAssembly smart contracts. Any language that compiles to Wasm can be used. But the code should be compatible with
To avoid unnecessary complexity, and boilerplate code, the best way is to use an eDSL that specifically targets the
ink! (based on Rust) or
ask! (based on AssemblyScript). More supported language and eDSL will come as the ecosystem grows.
The Wasm blob is then deployed and stored on-chain.
Similar to Substrate,
pallet-contracts uses weight to charge execution.
One gas is equivalent to one weight, defined as one picosecond of execution time on the runtime's reference machine.
automatic deposit collection
Additionally to the weight, there is also a fee paid for on-chain storage called automatic deposit collection. This additional fee is paid by the caller and is calculated with the price set for each storage item
DepositPerItem and the price charged for each byte of storage
The automatic deposit collection can be simplified as follows:
A caller of a contract pays a deposit to each contract in which new storage was created as a result of the executed call. In a similar way, a caller gets a refund from all the contracts that the call removed storage from.
Loading from storage weight
In order to prevent from theoretical PoV attack, as contract's WASM blob should be loaded from storage to be sent via network for state changes validation (included into PoV), a weight per byte of code is charged when loading a contract from storage.
Pallet-contracts uses wasmi as a wasm-interpreter to execute the smart-contract Wasm blob. Even though there is a faster JIT interpreter like wasmtime used in the native runtime, smart contracts are an untrusted environment and that’s why the high degree of correctness of wasmi makes it the best option.
Two-step Deployment of Contracts
The contract code (Wasm blob) and the contract address and storage are decoupled from each other. To deploy a non-existing contract on-chain:
- First, upload the Wasm contract on-chain (every contract Wasm code has a
code_hashas an identifier).
- Second, instantiate the contract - it will create an address and storage for that contract.
- Anyone can instantiate a contract based on its
There are several perks of decoupling contract code and address/storage:
- It will save space on-chain. Since a contract can have several constructors and several instantiations, it will just create a new instance based on the same underlying code. Think about standardized tokens, like PSP22 & PSP34, that will have one
blobleaving on-chain, and as many instantiations as it is needed rather than having code uploaded at each new instantiation (like in Ethereum).
- To instantiate a contract from within contract code (see delegator example), only
code_hashneeds to be provided.
- Some standards contracts (PSP22, PSP34) will only be uploaded on-chain once, preventing users from paying the gas fees of uploading new code.
- Update contract code for an address: replace the contract code at the specified address with a new code (see set_code_hash). Storage and balances will be preserved.
To facilitate development it is better to use a language targeting specifically
There are two eDSLs currently available
The only library available to communicate with smart contracts is PolkadotJS API.
Parity also developed a web application to interact with contracts called contracts-ui.
Stack comparison to Ethereum
|L1 Architecture||Ethereum clients||Substrate|
|Smart Contract Runtime Environment||EVM||pallet-contract, EVM via frontier|
|Gas Model||fixed price per instruction||weight + storage fees + loading fees|
|Smart Contract DSLs||Solidity and Vyper||ink! (Rust) and ask! (AssemblyScript)|