Skip to content

Commit 2e5bc93

Browse files
Add #[ink::contract_ref] attribute docs (#498)
* Add `#[ink::contract_ref]` attribute docs * migration: Add `ink::contract_ref` rename * note: `#[ink::contract_ref]` and `#[ink::trait_definition]` differences * title image
1 parent 725ba7c commit 2e5bc93

File tree

4 files changed

+281
-0
lines changed

4 files changed

+281
-0
lines changed

docs/faq/migrating-from-ink-5-to-6.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,14 @@ and have your contract invoke either a cross-contract call or a delegate call in
255255

256256
This is also the migration path recommended for Chain Extensions.
257257

258+
### Renamed `ink::contract_ref!` to `ink::contract_ref_from_path!`
259+
260+
This was necessary because we introduced a new [`#[ink::contract_ref]` attribute][contract-ref-attr].
261+
The PR [#2648](https://github.com/use-ink/ink/pull/2648) contains more information
262+
about the motivation and benefits of this change.
263+
264+
[contract-ref-attr]: ../macros-attributes/contract_ref.md
265+
258266
## Interesting New Features
259267

260268
### Solidity ABI compatible ink! contracts
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
---
2+
title: "#[ink::contract_ref]"
3+
hide_title: true
4+
slug: /macros-attributes/contract_ref
5+
---
6+
7+
![Text/contract_ref Title Picture](/img/title/text/contract_ref.svg)
8+
9+
Defines the interface of a "callee" contract and generates a wrapper type which can be
10+
used for interacting with the contract.
11+
12+
The interface is defined using a trait, and the macro generates a native Rust type
13+
(a contract reference) that implements this trait, so it can be used in any Rust
14+
context that expects types.
15+
16+
:::note
17+
A key difference between an `#[ink::contract_ref]` and [`#[ink::trait_definition]`][trait-def]
18+
is that a `#[ink::contract_ref]` dynamically declares the interface of
19+
an on-chain/"callee" contract with a possibly different ABI from the root/"caller" contract,
20+
while a [`#[ink::trait_definition]`][trait-def] is an interface that defines shared behavior
21+
to be implemented (or reused/inherited) by the root contract, where the ABI is
22+
inferred from the root contract.
23+
:::
24+
25+
[trait-def]: ../basics/trait-definitions.md
26+
27+
## Example
28+
29+
### Definition
30+
31+
```rust
32+
#[ink::contract_ref(abi = "sol")]
33+
pub trait Erc20 {
34+
Returns the total supply of the ERC-20 smart contract.
35+
#[ink(message)]
36+
fn total_supply(&self) -> ink::U256;
37+
38+
Transfers balance from the caller to the given address.
39+
#[ink(message)]
40+
fn transfer(&mut self, amount: ink::U256, to: ink::Address) -> bool;
41+
42+
// etc.
43+
}
44+
```
45+
46+
### Usage
47+
48+
Given the above interface, you can use the generated contract reference in a
49+
"caller" contract as shown below:
50+
51+
```rust
52+
#[ink::contract]
53+
mod erc20_caller {
54+
use ink::U256;
55+
56+
#[ink(storage)]
57+
pub struct Erc20Caller {
58+
callee: ink::Address,
59+
}
60+
61+
impl Erc20Caller {
62+
#[ink(constructor)]
63+
pub fn new(addr: ink::Address) -> Self {
64+
Self { callee: addr }
65+
}
66+
67+
#[ink(message)]
68+
pub fn call_erc20(&self) {
69+
// Calls the ERC20 contract using the contract ref generated above.
70+
let total = Erc20Ref::from(self.callee).total_supply();
71+
72+
// Do some fun stuff!
73+
}
74+
}
75+
}
76+
```
77+
78+
## Header Arguments
79+
80+
The `#[ink::contract_ref]` macro can be provided with some additional
81+
comma-separated header arguments:
82+
83+
### `abi: String`
84+
85+
Specifies the ABI (Application Binary Interface) of the "callee" contract.
86+
87+
**Usage Example:**
88+
```rust
89+
#[ink::contract_ref(abi = "sol")]
90+
pub trait Callee {
91+
#[ink(message)]
92+
fn message1(&self);
93+
94+
#[ink(message, selector = 42)]
95+
fn message2(&self);
96+
}
97+
```
98+
99+
**Default value:** Empty.
100+
101+
**Allowed values:** `"ink"`, `"sol"`
102+
103+
**NOTE**: When no value is provided, the generated contract reference will use the
104+
ABI of the root contract (i.e "ink" in ["ink" and "all" ABI mode][abi-mode]
105+
and "sol" in ["sol" ABI mode][abi-mode]).
106+
107+
[abi-mode]: ../basics/abi/overview.md
108+
109+
### `env: impl Environment`
110+
111+
Specifies the environment to use for the generated contract reference.
112+
113+
This should be the same environment used by the root contract (if any).
114+
115+
The environment must implement the `Environment` (defined in `ink_env`)
116+
trait and provides all the necessary fundamental type definitions for `Balance`,
117+
`AccountId` etc.
118+
119+
**Usage Example:**
120+
121+
Given a custom `Environment` implementation:
122+
```rust
123+
#[derive(Clone)]
124+
pub struct MyEnvironment;
125+
126+
impl ink_env::Environment for MyEnvironment {
127+
const NATIVE_TO_ETH_RATIO: u32 = 100_000_000;
128+
type AccountId = [u8; 16];
129+
type Balance = u128;
130+
type Hash = [u8; 32];
131+
type Timestamp = u64;
132+
type BlockNumber = u32;
133+
type EventRecord = ();
134+
}
135+
```
136+
A user might define an interface (and generate a contract reference) that uses the
137+
above custom `Environment` implementation as demonstrated below:
138+
```rust
139+
#[ink::contract_ref(env = MyEnvironment)]
140+
pub trait Callee {
141+
#[ink(message)]
142+
fn message(&self);
143+
144+
// ...
145+
}
146+
```
147+
148+
**Default value:** `DefaultEnvironment` defined in `ink_env` crate.

sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ module.exports = {
7373
"Macros & Attributes": [
7474
"macros-attributes/overview",
7575
"macros-attributes/contract",
76+
"macros-attributes/contract_ref",
7677
"macros-attributes/anonymous",
7778
"macros-attributes/constructor",
7879
"macros-attributes/default",
Lines changed: 124 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)