Solidity & MetaMask Compatibility
With ink! v6, we have introduced an abi
field in a custom ink-lang
table
in the package.metadata
table of a contract's manifest
file (i.e. the Cargo.toml
file) - more details here.
It allows building your contract in Solidity ABI compatibility mode
when declared as follows:
[package.metadata.ink-lang]
abi = "sol"
The implication of supporting Solidity ABI encoding is that all types used as constructor/message argument and return types, and event argument types must define a mapping to an equivalent Solidity ABI type.
Rust/ink! to Solidity ABI type mapping
This mapping is defined using the SolEncode
and
SolDecode
traits, which are analogs to
scale::Encode
and scale::Decode
(but for Solidity ABI encoding/decoding).
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.
Default/provided mappings
SolEncode
and SolDecode
are implemented
for the following Rust/ink! primitive types creating a mapping
to the corresponding Solidity ABI types as shown in the table below:
Rust/ink! type | Solidity ABI type | Notes |
---|---|---|
bool | bool | |
iN for N ∈ {8,16,32,64,128} | intN | e.g i8 ↔ int8 |
uN for N ∈ {8,16,32,64,128} | uintN | e.g u8 ↔ uint8 |
ink::U256 | uint256 | |
String | string | |
Box<str> | string | |
ink::Address / ink::H160 | address | ink::Address is a type alias for the ink::H160 type used for addresses in pallet-revive |
[T; N] for const N: usize | T[N] | e.g. [i8; 64] ↔ int8[64] |
Vec<T> | T[] | e.g. Vec<i8> ↔ int8[] |
Box<[T]> | T[] | e.g. Box<[i8]> ↔ int8[] |
ink::SolBytes<u8> | bytes1 | |
ink::SolBytes<[u8; N]> for 1 <= N <= 32 | bytesN | e.g. ink::SolBytes<[u8; 1]> ↔ bytes1 |
ink::SolBytes<Vec<u8>> | bytes | |
ink::SolBytes<Box<[u8]>> | bytes | |
(T1, T2, T3, ... T12) | (U1, U2, U3, ... U12) | where T1 ↔ U1 , ... T12 ↔ U12 e.g. (bool, u8, Address) ↔ (bool, uint8, address) |
SolEncode
is additionally implemented for reference and smart
pointer types below:
Rust/ink! type | Solidity ABI type | Notes |
---|---|---|
&str , &mut str | string | |
&T , &mut T , Box<T> | T | e.g. &i8 ↔ int8 |
&[T] , &mut [T] | T[] | e.g. &[i8] ↔ int8[] |
Rust's Option
and Result
types are notable omissions from the default mappings.
This is because they don't have semantically equivalent Solidity ABI types.
Mappings for arbitrary custom types
See the rustdoc for SolEncode
and SolDecode
for instructions for implementing the traits for arbitrary custom types.
Rust's coherence/orphan rules mean that you can
only implement the SolEncode
and SolDecode
traits for local types.
MetaMask
You can use MetaMask to interact with your ink!
smart contract via the Solidity ABI.
To set up your wallet and connect to the appropriate network, follow this quick start guide: Connect MetaMask to Polkadot Hub Testnet
Network name: Polkadot Hub TestNet
Currency symbol: PAS
Chain ID: 420420422
RPC URL: https://testnet-passet-hub-eth-rpc.polkadot.io
Block explorer URL: https://blockscout-passet-hub.parity-testnet.parity.io/
For step-by-step manual configuration instructions, see this guide: Connect MetaMask to Polkadot Hub Testnet.
Solidity Tooling
You can deploy and interact with ink!
smart contracts using popular Solidity tools like Hardhat and Foundry thanks to the Solidity-compatible ABI output.
Full Tutorial: Use Solidity Tooling with ink! Contracts
This guide walks through compiling an ink!
contract with Solidity metadata, configuring Hardhat, deploying to the Polkadot Hub Testnet, and interacting with the contract using Ethers.js.
Block explorers
PolkaVM smart contracts are compatible with Ethereum-style block explorers such as BlockScout, which is already integrated with the Polkadot Hub Testnet.
For additional information and instructions, check out: Polkadot Smart Contract Block Explorers