Skip to content

ABI docs #411

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,37 @@ slug: /background/solidity-metamask-compatibility

# Solidity & MetaMask Compatibility

With ink! v6, we have introduced a new attribute argument `abi` for the `#[ink::contract]` macro.
It allows building your contract in Solidity ABI compatibility mode ([more details here][contract-abi-arg]).
With ink! v6, we have introduced an `abi` field in a custom `ink-lang` table
in the [`package.metadata` table][package-metadata] of a contract's manifest
file (i.e. the `Cargo.toml` file) - [more details here][abi-declaration].
It allows building your contract in Solidity ABI compatibility mode
when declared as follows:

The implication of supporting Solidity ABI encoding is that all types used as constructor/message arguments
and return types must define a mapping to an equivalent Solidity type.
```toml
[package.metadata.ink-lang]
abi = "sol"
```

This mapping is defined using the [`SolEncode`][sol-trait-encode] and [`SolDecode`][sol-trait-decode] traits,
which are analogs to [`scale::Encode` and `scale::Decode`][scale-codec] (but for Solidity ABI encoding/decoding).
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.

[package-metadata]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-metadata-table
[abi-declaration]: ../basics/abi/overview.md#declaring-the-abi

## Rust/ink! to Solidity ABI type mapping

This mapping is defined using the [`SolEncode`][sol-trait-encode] and
[`SolDecode`][sol-trait-decode] traits, which are analogs to
[`scale::Encode` and `scale::Decode`][scale-codec]
(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.

[contract-abi-arg]: ../macros-attributes/contract.md#abi-string
[sol-trait-encode]: https://docs.rs/ink/latest/ink/trait.SolEncode.html
[sol-trait-decode]: https://docs.rs/ink/latest/ink/trait.SolEncode.html
[scale-codec]: https://docs.rs/parity-scale-codec/latest/parity_scale_codec

## Rust/ink! to Solidity ABI type mapping

### Default/provided mappings

[`SolEncode`][sol-trait-encode] and [`SolDecode`][sol-trait-decode] are implemented
Expand Down
51 changes: 51 additions & 0 deletions versioned_docs/version-v6/basics/abi/all.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: |
"All" ABI Mode
hide_title: true
slug: /basics/abi/all
---

![Metadata Title Picture](/img/title/metadata-revive.svg)

# "All" ABI Mode

The "all" ABI mode is declared in the contract's manifest file (i.e. the `Cargo.toml` file)
as follows:

```toml
[package.metadata.ink-lang]
abi = "all"
```

When the "all" ABI is specified, the ink! code generator follows both
the ink! and Solidity ABI specifications, and generates entry points
for both calling conventions. This means:

- For each message, two selectors are generated, one for [ink!](./ink)
and another for [Solidity](./solidity) ABI.
- Each selector is ABI specific and its entry point uses the corresponding
input/output encoding/decoding scheme (i.e. entry points for ink! selectors use
Parity's [SCALE Codec][scale-codec], while entry points for Solidity selectors
use Solidity ABI encoding/decoding for input/output encoding/decoding).
- Message selector manual overrides
(using the [`selector` attribute][selector-attribute]) are respected for
ink! ABI entry points but ignored for Solidity ABI entry points
(i.e. Solidity selectors are **always** generated according to the
[Solidity ABI specification for function selectors][sol-abi-selector]).
- Call builders are generated for both ink! and Solidity ABI calling conventions,
and a `_sol` suffix is used to disambiguate Solidity calls.

:::note
Your contract sizes will get larger if you support both the ink! and Solidity ABI.
:::

:::note
The "all" ABI mode can only be used if all constructor and message
argument and return types, and event argument types can be mapped to
equivalent Solidity ABI types ([more details here][sol-type-mapping]).
:::

[scale-codec]: https://docs.rs/parity-scale-codec/latest/parity_scale_codec
[sol-abi-selector]: https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector
[selector-attribute]: ../../macros-attributes/selector
[sol-type-mapping]: ../../background/solidity-metamask-compat.md#rustink-to-solidity-abi-type-mapping
31 changes: 31 additions & 0 deletions versioned_docs/version-v6/basics/abi/ink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: ink! ABI
hide_title: true
slug: /basics/abi/ink
---

![Metadata Title Picture](/img/title/metadata-revive.svg)

# ink! ABI

The ink! ABI is declared in the contract's manifest file (i.e. the `Cargo.toml` file)
as follows:

```toml
[package.metadata.ink-lang]
abi = "ink"
```

When the ink! ABI is specified, the ink! code generator follows the ink! ABI specification.
This means:

- By default, message selectors are generated according to the
[ink! ABI specification for selectors][ink-spec-selector].
- Message selectors can be manually overridden using the [`selector` attribute][selector-attribute].
- Parity's [SCALE Codec][scale-codec] is used for input/output encoding/decoding.
- Call builders (used for making cross-contract calls) are generated for ink! ABI
calling conventions.

[ink-spec-selector]: ../../basics/selectors
[selector-attribute]: ../../macros-attributes/selector
[scale-codec]: https://docs.rs/parity-scale-codec/latest/parity_scale_codec
63 changes: 63 additions & 0 deletions versioned_docs/version-v6/basics/abi/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: Overview
hide_title: true
slug: /basics/abi
---

![Metadata Title Picture](/img/title/metadata-revive.svg)

# ABI (Application Binary Interface)

An ABI (Application Binary Interface) defines a standard way to interact with contracts
(i.e. it defines the calling conventions to use for message calls).

More concretely this entails:
- Specifications for generating selectors which identify the entry points
for message/function calls
- Specifications for encoding and decoding message/function arguments and return types,
as well as event and error argument types

With ink! v6, the ink! code generator supports two ABI specifications:

- [Our own native ink! ABI specification](./ink.md)
- [The Solidity ABI specification](./solidity.md)

Supporting the Solidity ABI specification allows:
- Solidity contracts to transparently call ink! contracts
- Developers to use Solidity tools (e.g. [ethers.js][ethers-js]) to
transparently interact with ink! contracts.

Additionally, the ink! code generator can operate in an [`"all"` ABI mode](./all.md),
where it generates a binary that supports both the ink! and Solidity ABI specifications
(i.e. it generates a binary that transparently supports both ink! and Solidity
calling conventions, and thus transparently supports interactions from
both ink! and Solidity contracts and external tools).

## Declaring the ABI

The ABI for an ink! contract is declared in the contract's manifest file
(i.e. the `Cargo.toml` file), as a field `abi` of a custom `ink-lang` table
in the [`package.metadata` table][package-metadata] e.g.

```toml
[package.metadata.ink-lang]
abi = "sol"
```

The default value for `abi` is `"ink"`.

Allowed values are `"ink"`, `"sol"` and `"all"`.

:::note
The Solidity ABI specification can only be used if all constructor and message
argument and return types, and event argument types can be mapped to
equivalent Solidity ABI types ([more details here][sol-type-mapping]).
:::

:::note
Your contract sizes will get larger if you support both the ink! and Solidity ABI.
:::

[package-metadata]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-metadata-table
[ethers-js]: https://docs.ethers.org/
[sol-type-mapping]: ../../background/solidity-metamask-compat.md#rustink-to-solidity-abi-type-mapping
38 changes: 38 additions & 0 deletions versioned_docs/version-v6/basics/abi/solidity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Solidity ABI
hide_title: true
slug: /basics/abi/solidity
---

![Metadata Title Picture](/img/title/solidity.svg)

# Solidity ABI

The Solidity ABI is declared in the contract's manifest file (i.e. the `Cargo.toml` file)
as follows:

```toml
[package.metadata.ink-lang]
abi = "sol"
```

When the Solidity ABI is specified, the ink! code generator follows the [Solidity ABI specification][sol-abi].
This means:

- Message selectors are **always** generated according to the
[Solidity ABI specification for function selectors][sol-abi-selector].
- Message selector manual overrides using the [`selector` attribute][selector-attribute] are ignored.
- [Solidity ABI encoding][sol-abi-codec] is used for input/output encoding/decoding.
- Call builders are generated for Solidity ABI calling conventions.

:::note
The Solidity ABI specification can only be used if all constructor and message
argument and return types, and event argument types can be mapped to
equivalent Solidity ABI types ([more details here][sol-type-mapping]).
:::

[sol-abi]: https://docs.soliditylang.org/en/latest/abi-spec.html
[sol-abi-selector]: https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector
[selector-attribute]: ../../macros-attributes/selector
[sol-abi-codec]: https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding
[sol-type-mapping]: ../../background/solidity-metamask-compat.md#rustink-to-solidity-abi-type-mapping
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: Metadata
title: Overview
hide_title: true
slug: /basics/metadata
---
Expand Down Expand Up @@ -39,8 +39,8 @@ $ cargo contract build ---metadata <ink|solidity>
```

Generating Solidity metadata is only possible if all constructor and message
arguments and return types can be mapped to equivalent Solidity ABI types
([more details here][sol-type-mapping]).
argument and return types, and event argument types can be mapped to
equivalent Solidity ABI types ([more details here][sol-type-mapping]).

[ethers-js]: https://docs.ethers.org/
[sol-compat]: ../../background/solidity-metamask-compat.md
Expand Down
2 changes: 1 addition & 1 deletion versioned_docs/version-v6/basics/selectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Selectors in ink! are a language agnostic way of identifying constructors and me
They are four-byte hexadecimal strings which look something like: `0x633aa551`.

You can find the selector of an ink! constructor or message in your
[contract metadata](./metadata/metadata.md) by looking for the `selector` field of the dispatchable
[contract metadata](./metadata/overview.md) by looking for the `selector` field of the dispatchable
you're interested in.

Here is an example of how you can grab the message name and selector from your contract
Expand Down
82 changes: 0 additions & 82 deletions versioned_docs/version-v6/macros-attributes/contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,88 +25,6 @@ proper code.
The `#[ink::contract]` macro can be provided with some additional comma-separated
header arguments:

### `abi: String`

Tells the ink! code generator which ABI (Application Binary Interface)
specification(s) to support for contract interactions
(i.e. which calling conventions to use for message calls).

**Default value:** `"ink"`

**Allowed values:** `"ink"`, `"sol"`, `"all"`

**Usage Example:**
```rust
#[ink::contract(abi = "sol")]
mod my_contract {
#[ink(storage)]
pub struct MyStorage;

impl MyStorage {
#[ink(constructor)]
pub fn construct() -> Self { MyStorage {} }

#[ink(message)]
pub fn message(&self) {}
}

// ...
}
```

#### `abi = "ink"`

The code generator follows the ink! ABI specification. This means:
- By default, message selectors are generated according to the
[ink! ABI specification for selectors][ink-spec-selector].
- Message selectors can be manually overridden using the `selector` attribute.
- Parity's [SCALE Codec][scale-codec] is used for input/output encoding/decoding.
- Call builders (used for making cross-contract calls) are generated for ink! ABI
calling conventions.

#### `abi = "sol"`

The code generator follows the [Solidity ABI specification][sol-abi]. This means:

- Message selectors are **always** generated according to the
[Solidity ABI specification for function selectors][sol-abi-selector].
- Message selector manual overrides using the `selector` attribute are ignored.
- [Solidity ABI encoding][sol-abi-codec] is used for input/output encoding/decoding.
- Call builders are generated for Solidity ABI calling conventions.

#### `abi = "all"`

The code generator follows both the ink! and Solidity ABI specifications, and
generates entry points for both calling conventions. This means:

- For each message, two selectors are generated, one for ink! and another for
Solidity ABI.
- Each selector is ABI specific and its entry point uses the corresponding
input/output encoding/decoding scheme (i.e. entry points for ink! selectors use
Parity's [SCALE Codec][scale-codec], while entry points for Solidity selectors
use Solidity ABI encoding/decoding for input/output encoding/decoding).
- Message selector manual overrides (using the `selector` attribute) are respected
for ink! ABI entry points but ignored for Solidity ABI entry points
(i.e. Solidity selectors are **always** generated according to the
[Solidity ABI specification for function selectors][sol-abi-selector]).
- Call builders are generated for both ink! and Solidity ABI calling conventions,
and a `_sol` suffix is used to disambiguate Solidity calls.

:::note
Your contract sizes will get larger if you support both the ink! and Solidity ABI.
:::

For contracts that support Solidity ABI encoding (i.e. `abi = "sol"` or `abi = "all"`),
all types used as constructor/message arguments and return types must define a mapping
to an equivalent Solidity type ([more details here][sol-type-mapping]).

[ink-spec-selector]: https://use.ink/basics/selectors/
[scale-codec]: https://docs.rs/parity-scale-codec/latest/parity_scale_codec
[sol-abi]: https://docs.soliditylang.org/en/latest/abi-spec.html
[sol-abi-selector]: https://docs.soliditylang.org/en/latest/abi-spec.html#function-selector
[sol-abi-codec]: https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding
[sol-type-mapping]: ../background/solidity-metamask-compat.md#rustink-to-solidity-abi-type-mapping

### `keep_attr: String`

Tells the ink! code generator which attributes should be passed to call builders.
Expand Down
20 changes: 15 additions & 5 deletions versioned_sidebars/version-v6-sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,24 @@
"basics/upgradeability",
"basics/env-functions",
"basics/environment",
{
"type": "category",
"label": "ABI",
"items": [
"basics/abi/overview",
"basics/abi/ink",
"basics/abi/solidity",
"basics/abi/all"
]
},
{
"type": "category",
"label": "Metadata",
"items": ["basics/metadata/ink-format", "basics/metadata/solidity-format"],
"link": {
"type": "doc",
"id": "basics/metadata/metadata"
}
"items": [
"basics/metadata/overview",
"basics/metadata/ink-format",
"basics/metadata/solidity-format"
]
},
"basics/xcm",
"basics/contract-verification"
Expand Down