Skip to content

v6.0.0-alpha

Pre-release
Pre-release

Choose a tag to compare

@AlexD10S AlexD10S released this 02 May 19:49
· 163 commits to master since this release
02a1d05

This is our first alpha release for ink! v6. We release it together with cargo-contract v6.0.0-alpha.

The biggest change is that we are in the process of migrating from pallet-contracts +
WebAssembly (executed in wasmi) to pallet-revive +
RISC-V (executed in PolkaVM).
This is a major breaking change, ink! v6 will only be compatible with cargo-contract >= v6
and chains that include pallet-revive.

We did a detailed write-up of the background to this development and the reasoning
here. We also updated the ink/ARCHITECTURE.md
to reflect the new setup.

Compatibility of this release:

In the following we'll describe some breaking changes on a high-level. The
context to understand them is that the pallet-revive team has Ethereum/Solidity
support as the number one priority. All their design decisions derive from that,
they don't want to maintain code that is unnecessary for that objective.

🚧 This is an alpha release, changes will still happen and there are rough edges. 🚧

Cross-contract calling Solidity contracts

We are introducing a new attribute abi for the #[ink::contract] macro.
These are the values it takes:

#[ink::contract(abi = "all")]
#[ink::contract(abi = "sol")]
#[ink::contract(abi = "ink")]

The default currently is abi = "ink", but we might change this before a production
release.

The implication of supporting Solidity ABI encoding is that there is a restriction on
the types you can use as constructor/message arguments or return types.
You won't be able to use Rust types for which no mapping to a Solidity type exists.
An error about a missing trait implementation for this type will be thrown.

Please note that your contract sizes will get larger if you support both the ink!
and Solidity ABI.

Types

Contract Balance: U256

For the type of a contract's balance, pallet-revive uses depending on the context

  • either the configured pallet_revive::Config::Currency type (which corresponds
    to the ink::Environment::Balance type.
  • or a hardcoded U256 (which corresponds to what Ethereum uses).
    In this alpha release we just adhere to requiring the types that pallet-revive uses.
    In an upcoming beta release this could be simplified to reduce UX friction by just
    using one type everywhere and converting to the pallet-revive one.

Contract Address: Address / H160

For a contract's account, pallet-revive is using either the configured AccountId type
of the polkadot-sdk runtime, or H160.

Address is a more semantically named type alias for H160 defined in ink_primitives,
and re-exported in the ink crate.

Finding the Address/H160 for an AccountId is done via an address derivation scheme
derived in #7662.
After instantiating a contract, the address is no longer returned by pallet-revive.
Instead one has to derive it from given parameters (see the linked PR). cargo-contract
does that automatically.

For contract instantiations and contract calls the pallet requires that a 1-to-1 mapping
of an AccountId to an Address/H160 has been created. This can be done via the
map_account/unmap_account API.
The PR #6096 contains more
information.

Besides the publicly exposed crate functions, we've introduced a new subcommand
cargo contract account that allows resolving the H160 contract address to the
Substrate AccountId which it is mapped to.

Contract Hash: H256

For a contract's hash value, pallet-revive uses a fixed H256, Previously,
the ink::Environment::Hash type referenced the hash type being used for the
contract's hash. Now it's just a fixed H256.

Contract delegates can no longer be done by code

In pallet-contracts (and hence up until ink! v5), a pattern for upgradeable
contracts was to delegate the contract execution to a different code, e.g. to
a new version of the contract's code.

This distinction of contract code that was uploaded to a chain vs. an instantiated
contract from this code no longer exists in pallet-revive. If you want to
delegate the execution, you will have to specify another contract's address
to which code you want to delegate to. This other contract needs to be instantiated
on-chain.

For the execution, the context of the contract that delegates will continue
to be used (storage, caller, value).

Specifically the delegate API changed like this:

/// ink! v5
#[derive(Clone)]
pub struct DelegateCall<E: Environment> {
    code_hash: E::Hash,
    call_flags: CallFlags,
}

/// ink! v6
#[derive(Clone)]
pub struct DelegateCall {
    address: H160,
    flags: CallFlags,
    ref_time_limit: u64,
    proof_size_limit: u64,
    deposit_limit: Option<[u8; 32]>,
}

Feature ink/unstable-hostfn

In pallet-revive a number of functions can only be called by smart contracts
if the chain that the pallet is running on has enabled the feature
pallet-revive/unstable-hostfn.
This feature is not enabled on Kusama or Westend!

It is enabled for the substrate-contracts-node version that we linked above.

New debugging workflow

Previously pallet-contracts returned a debug_message field with contract
instantiations and dry-runs.
Whenever ink::env::debug_println was invoked in a contract, ink! wrote debugging
info to this field. This functionality has been removed. Instead pallet-revive now
supports other means of debugging.

The most relevant new debugging workflow is the tracing API. There are a number
of PRs that implemented it, so we won't link a specific one here. A good starting
point to look deeper into it is the tracing.rs.

We have implemented barebones support for this tracing API in the 6.0.0-alpha
versions of ink! + cargo-contract. But it's really barebones and should
certainly be improved before a production release.

Please see our developer documentation
for more details.
We've also added a contract example to illustrate these new debugging strategies:
debugging-strategies.

Restrictions which cfg attributes can be used

This change was done as a recommendation from the ink! 5.x audit.
In a nutshell it prevents developers from hiding functionality in a contract,
that would not be visible in the metadata (so e.g. on a block explorer).
The relevant PR is #2313.

From ink! 6.0 on only these attributes are allowed in #[cfg(…)]:

  • test
  • feature (without std)
  • any
  • not
  • all

Metadata Changes

The field source.wasm was renamed to source.contract_binary.

no_main

Previously ink! contracts started with this line:

#![cfg_attr(not(feature = "std"), no_std)]

This line instructs the Rust compiler to not link the Rust
standard library with your contract.
If you want to know about why:
we have an entry
"Why is Rust's standard library (stdlib) not available in ink!?"
Please see our developer documentation
in our FAQ.

With ink! v6, an additional crate-level attribute needs to be set:

#![cfg_attr(not(feature = "std"), no_std, no_main)]

It instructs the compiler not to use the default fn main() {} function as the
entry point for your smart contract. This is needed because PolkaVM uses a different
entry point (the deploy function).

substrate-contracts-node can no longer be used

The substrate-contracts-node is still maintained by Parity for ink! v5 and
pallet-contracts, but it does not support pallet-revive.

We've set up a new project in its place: ink-node.
As before, it functions as a simple local development node.
It contains pallet-revive in a default configuration.
You can find binary releases of the node here.

Changed

  • Restrict which cfg attributes can be used ‒ #2313
  • More idiomatic return types for metadata getters - #2398
  • Define static distributed events slice in ink crate - #2487

Added

  • Support for caller_is_root - #2332
  • Allow setting features for contract build in E2E tests - #2460
  • Improve support for Solidity ABI calling conventions - #2411
  • Implement contract invocation in off-chain environment engine - #1957
  • Abstractions for mapping arbitrary Rust types to Solidity ABI compatible types - #2441
  • Documentation for contract abi arg and provided Rust/ink! to Solidity type mappings - 2463
  • Implement SolDecode, SolTypeDecode and support SolBytes for boxed slices - 2476

Fixed

  • [E2E] Have port parsing handle comma-separated list ‒ #2336
  • Always use ink! ABI/ SCALE codec for constructor and instantiation related builders and utilities - #2474
  • Get rid of "extrinsic for call failed: Pallet error: Revive::AccountAlreadyMapped" - 2483
  • CI disk usage via standardised toolchains: stable 1.86, nightly 2025-02-20 - #2484
  • CI contract size submission - #2490
  • CI relax criteria for measurements-master artifact lookup - #2491