Skip to content

Commit 5065fbc

Browse files
Refactor multi ABI interfaces (#2618)
* env: multi ABI interface for call and create builders * ink: multi ABI interface for emit emission for `EnvAccess` * codegen: multi ABI interface for contract refs * tests: Update integration tests * tests: Update ui tests * chore: clippy * Update changelog * docs Co-authored-by: Michael Müller <[email protected]> --------- Co-authored-by: Michael Müller <[email protected]>
1 parent 8c9390f commit 5065fbc

File tree

12 files changed

+100
-43
lines changed

12 files changed

+100
-43
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
### Changed
1313
- Synchronize with `polkadot-sdk/c40b36c3a7c208f9a6837b80812473af3d9ba7f7`[2589](https://github.com/use-ink/ink/pull/2589)
1414
- Synchronize with `polkadot-sdk/a71ec19a94702ea71767ba5ac97603ea6c6305c1`[2619](https://github.com/use-ink/ink/pull/2619)
15+
- Refactor multi ABI interfaces - [#2618](https://github.com/use-ink/ink/pull/2618)
1516

1617
### Removed
1718
- Removed functionalities around calling into the runtime and chain extensions ‒ [2621](https://github.com/use-ink/ink/pull/2621)

crates/env/src/call/call_builder/mod.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ pub use delegate::DelegateCall;
2121
use core::marker::PhantomData;
2222

2323
use ink_primitives::{
24-
abi::Sol,
24+
abi::{
25+
Ink,
26+
Sol,
27+
},
2528
Address,
2629
};
2730

@@ -232,14 +235,15 @@ where
232235
}
233236
}
234237

235-
/// Returns a new [`CallBuilder`] for the specified ABI to build up the parameters to a
236-
/// cross-contract call.
238+
/// Returns a new [`CallBuilder`] to build up the parameters to a cross-contract call
239+
/// that uses ink! ABI Encoding (i.e. with SCALE codec for input/output encode/decode).
240+
///
237241
/// See [`build_call`] for more details on usage.
238242
#[allow(clippy::type_complexity)]
239-
pub fn build_call_abi<E, Abi>() -> CallBuilder<
243+
pub fn build_call_ink<E>() -> CallBuilder<
240244
E,
241245
Unset<Call>,
242-
Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
246+
Unset<ExecutionInput<EmptyArgumentList<Ink>, Ink>>,
243247
Unset<ReturnType<()>>,
244248
>
245249
where
@@ -255,9 +259,10 @@ where
255259

256260
/// Returns a new [`CallBuilder`] to build up the parameters to a cross-contract call
257261
/// that uses Solidity ABI Encoding.
262+
///
258263
/// See [`build_call`] for more details on usage.
259264
#[allow(clippy::type_complexity)]
260-
pub fn build_call_solidity<E>() -> CallBuilder<
265+
pub fn build_call_sol<E>() -> CallBuilder<
261266
E,
262267
Unset<Call>,
263268
Unset<ExecutionInput<EmptyArgumentList<Sol>, Sol>>,

crates/env/src/call/create_builder.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use core::marker::PhantomData;
1717
use ink_primitives::{
1818
abi::{
1919
AbiEncodeWith,
20+
Ink,
2021
Sol,
2122
},
2223
Address,
@@ -472,17 +473,19 @@ where
472473
}
473474
}
474475

475-
/// Returns a new [`CreateBuilder`] for the specified ABI to build up the parameters to a
476-
/// cross-contract instantiation.
476+
/// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract
477+
/// instantiation that uses ink! ABI Encoding (i.e. with SCALE codec for input/output
478+
/// encode/decode).
479+
///
477480
/// See [`build_create`] for more details on usage.
478481
#[allow(clippy::type_complexity)]
479-
pub fn build_create_abi<ContractRef, Abi>() -> CreateBuilder<
482+
pub fn build_create_ink<ContractRef>() -> CreateBuilder<
480483
<ContractRef as ContractEnv>::Env,
481484
ContractRef,
482485
Set<LimitParamsV2>,
483-
Unset<ExecutionInput<EmptyArgumentList<Abi>, Abi>>,
486+
Unset<ExecutionInput<EmptyArgumentList<Ink>, Ink>>,
484487
Unset<ReturnType<()>>,
485-
Abi,
488+
Ink,
486489
>
487490
where
488491
ContractRef: ContractEnv,
@@ -504,9 +507,10 @@ where
504507

505508
/// Returns a new [`CreateBuilder`] to build up the parameters to a cross-contract
506509
/// instantiation that uses Solidity ABI Encoding.
510+
///
507511
/// See [`build_create`] for more details on usage.
508512
#[allow(clippy::type_complexity)]
509-
pub fn build_create_solidity<ContractRef>() -> CreateBuilder<
513+
pub fn build_create_sol<ContractRef>() -> CreateBuilder<
510514
<ContractRef as ContractEnv>::Env,
511515
ContractRef,
512516
Set<LimitParamsV2>,

crates/env/src/call/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,17 @@ pub mod utils {
4545
pub use self::{
4646
call_builder::{
4747
build_call,
48-
build_call_abi,
49-
build_call_solidity,
48+
build_call_ink,
49+
build_call_sol,
5050
Call,
5151
CallBuilder,
5252
CallParams,
5353
DelegateCall,
5454
},
5555
create_builder::{
5656
build_create,
57-
build_create_abi,
58-
build_create_solidity,
57+
build_create_ink,
58+
build_create_sol,
5959
state,
6060
ConstructorReturnType,
6161
CreateBuilder,

crates/ink/codegen/src/generator/as_dependency/call_builder.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,23 @@ impl CallBuilder<'_> {
452452
.map(quote::ToTokens::to_token_stream)
453453
.unwrap_or_else(|| quote::quote! { () });
454454
let output_span = return_type.span();
455-
let (selector_bytes, abi_ty) = match abi {
455+
let (selector_bytes, abi_ty, build_call_fn) = match abi {
456456
Abi::Ink => {
457457
let selector = message.composed_selector();
458458
let selector_bytes = selector.hex_lits();
459-
(quote!([ #( #selector_bytes ),* ]), quote!(::ink::abi::Ink))
459+
(
460+
quote!([ #( #selector_bytes ),* ]),
461+
quote!(::ink::abi::Ink),
462+
quote!(build_call_ink),
463+
)
464+
}
465+
Abi::Sol => {
466+
(
467+
sol::utils::selector(&message),
468+
quote!(::ink::abi::Sol),
469+
quote!(build_call_sol),
470+
)
460471
}
461-
Abi::Sol => (sol::utils::selector(&message), quote!(::ink::abi::Sol)),
462472
};
463473
let arg_list = generator::generate_argument_list(
464474
input_types.iter().cloned(),
@@ -480,7 +490,7 @@ impl CallBuilder<'_> {
480490
& #mut_tok self
481491
#( , #input_bindings : #input_types )*
482492
) -> #output_type {
483-
::ink::env::call::build_call_abi::<Environment, #abi_ty>()
493+
::ink::env::call::#build_call_fn::<Environment>()
484494
.call(::ink::ToAddr::to_addr(self))
485495
.exec_input(
486496
::ink::env::call::ExecutionInput::new(

crates/ink/codegen/src/generator/as_dependency/contract_ref.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use ir::{
2121
use itertools::Itertools;
2222
use proc_macro2::TokenStream as TokenStream2;
2323
use quote::{
24+
format_ident,
2425
quote,
2526
quote_spanned,
2627
};
@@ -65,9 +66,14 @@ impl GenerateCode for ContractRef<'_> {
6566
}
6667

6768
impl ContractRef<'_> {
69+
/// Generates the identifier of the contract reference struct.
70+
fn generate_contract_ref_base_ident(&self) -> syn::Ident {
71+
format_ident!("{}Ref", self.contract.module().storage().ident())
72+
}
73+
6874
/// Generates the identifier of the contract reference struct.
6975
fn generate_contract_ref_ident(&self) -> syn::Ident {
70-
quote::format_ident!("{}Ref", self.contract.module().storage().ident())
76+
format_ident!("{}For", self.generate_contract_ref_base_ident())
7177
}
7278

7379
/// Generates the code for the struct representing the contract reference.
@@ -89,6 +95,18 @@ impl ContractRef<'_> {
8995
let storage_ident = self.contract.module().storage().ident();
9096
let ref_ident = self.generate_contract_ref_ident();
9197
let abi = default_abi!();
98+
let ref_ident_default_abi = self.generate_contract_ref_base_ident();
99+
let ref_ident_abi_aliases = generate_abi_impls!(@type |abi| {
100+
let (abi_ty, suffix) = match abi {
101+
Abi::Ink => (quote!(::ink::abi::Ink), "Ink"),
102+
Abi::Sol => (quote!(::ink::abi::Sol), "Sol"),
103+
};
104+
let ref_ident_abi_alias = format_ident!("{ref_ident_default_abi}{suffix}");
105+
quote! {
106+
#[allow(dead_code)]
107+
pub type #ref_ident_abi_alias = #ref_ident::<#abi_ty>;
108+
}
109+
});
92110
let sol_codec = if cfg!(any(ink_abi = "sol", ink_abi = "all")) {
93111
// These manual implementations are a bit more efficient than the derived
94112
// equivalents.
@@ -132,6 +150,12 @@ impl ContractRef<'_> {
132150
_marker: core::marker::PhantomData<Abi>,
133151
}
134152

153+
// Default type alias (i.e. `ContractRef` for a contract named `Contract`).
154+
#[allow(dead_code)]
155+
pub type #ref_ident_default_abi = #ref_ident::<#abi>;
156+
// ABI specific type aliases (i.e. `ContractRefInk` and `ContractRefSol`) as appropriate.
157+
#ref_ident_abi_aliases
158+
135159
const _: () = {
136160
impl ::ink::env::ContractReference for #storage_ident {
137161
type Type = #ref_ident;
@@ -585,7 +609,7 @@ impl ContractRef<'_> {
585609
.map(quote::ToTokens::to_token_stream)
586610
.unwrap_or_else(|| quote::quote! { Self });
587611

588-
let (abi_ty, exec_input_init) = match abi {
612+
let (abi_ty, exec_input_init, build_create_fn) = match abi {
589613
Abi::Ink => {
590614
let selector_bytes = constructor.composed_selector().hex_lits();
591615
(
@@ -595,6 +619,7 @@ impl ContractRef<'_> {
595619
::ink::env::call::Selector::new([ #( #selector_bytes ),* ])
596620
)
597621
},
622+
quote!(build_create_ink),
598623
)
599624
}
600625
Abi::Sol => {
@@ -603,6 +628,7 @@ impl ContractRef<'_> {
603628
quote! {
604629
::ink::env::call::ExecutionInput::no_selector()
605630
},
631+
quote!(build_create_sol),
606632
)
607633
}
608634
};
@@ -625,7 +651,7 @@ impl ContractRef<'_> {
625651
::ink::env::call::utils::Set<::ink::env::call::utils::ReturnType<#ret_type>>,
626652
#abi_ty
627653
> {
628-
::ink::env::call::build_create_abi::<Self, #abi_ty>()
654+
::ink::env::call::#build_create_fn::<Self>()
629655
.exec_input(
630656
#exec_input_init
631657
#(

crates/ink/src/env_access.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ use ink_env::{
3131
},
3232
Environment,
3333
Result,
34-
TopicEncoder,
3534
};
3635
use ink_primitives::{
37-
abi::AbiEncodeWith,
36+
abi::{
37+
AbiEncodeWith,
38+
Ink,
39+
Sol,
40+
},
3841
Address,
3942
H256,
4043
U256,
@@ -408,13 +411,21 @@ where
408411
ink_env::emit_event::<E, Evt, crate::abi::Sol>(&event);
409412
}
410413

411-
/// Emits an event using the specified ABI.
412-
pub fn emit_event_abi<Evt, Abi>(self, event: Evt)
414+
/// Emits an event using the ink! ABI encoding (i.e. with SCALE codec for event data
415+
/// encode/decode).
416+
pub fn emit_event_ink<Evt>(self, event: Evt)
417+
where
418+
Evt: ink_env::Event<Ink>,
419+
{
420+
ink_env::emit_event::<E, Evt, Ink>(&event)
421+
}
422+
423+
/// Emits an event using the Solidity ABI encoding.
424+
pub fn emit_event_sol<Evt>(self, event: Evt)
413425
where
414-
Evt: ink_env::Event<Abi>,
415-
Abi: TopicEncoder,
426+
Evt: ink_env::Event<Sol>,
416427
{
417-
ink_env::emit_event::<E, Evt, Abi>(&event)
428+
ink_env::emit_event::<E, Evt, Sol>(&event)
418429
}
419430

420431
/// Instantiates another contract using the supplied code hash.

crates/ink/tests/ui/contract/fail/constructor/constructor-return-result-invalid.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ error[E0276]: impl has stricter requirements than trait
1818
18 | | }
1919
| |_________^ impl has extra requirement `ConstructorOutputValue<Result<u8, contract::Error>>: ConstructorOutput<contract::Contract>`
2020

21-
error[E0277]: the trait bound `Result<u8, contract::Error>: ConstructorReturnType<ContractRef, ink::abi::Ink>` is not satisfied
21+
error[E0277]: the trait bound `Result<u8, contract::Error>: ConstructorReturnType<ContractRefFor, ink::abi::Ink>` is not satisfied
2222
--> tests/ui/contract/fail/constructor/constructor-return-result-invalid.rs:16:33
2323
|
2424
16 | pub fn constructor() -> Result<u8, Error> {
25-
| - ^^^^^^^^^^^^^^^^^ the trait `ConstructorReturnType<ContractRef, ink::abi::Ink>` is not implemented for `Result<u8, contract::Error>`
25+
| - ^^^^^^^^^^^^^^^^^ the trait `ConstructorReturnType<ContractRefFor, ink::abi::Ink>` is not implemented for `Result<u8, contract::Error>`
2626
| _________|
2727
| |
2828
17 | | Ok(5_u8)
@@ -31,7 +31,7 @@ error[E0277]: the trait bound `Result<u8, contract::Error>: ConstructorReturnTyp
3131
|
3232
= help: the following other types implement trait `ConstructorReturnType<C, Abi>`:
3333
`Result<C, E>` implements `ConstructorReturnType<C, Abi>`
34-
`Result<contract::Contract, E>` implements `ConstructorReturnType<ContractRef, Abi>`
34+
`Result<contract::Contract, E>` implements `ConstructorReturnType<ContractRefFor, Abi>`
3535
note: required by a bound in `CreateBuilder::<E, ContractRef, Limits, Args, Unset<ReturnType<()>>, Abi>::returns`
3636
--> $WORKSPACE/crates/env/src/call/create_builder.rs
3737
|

crates/ink/tests/ui/contract/fail/constructor/constructor-return-result-non-codec-error.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ error[E0277]: the trait bound `contract::Error: WrapperTypeDecode` is not satisf
3434
sp_core::Bytes
3535
= note: required for `contract::Error` to implement `ink::parity_scale_codec::Decode`
3636
= note: required for `contract::Error` to implement `DecodeConstructorError<ink::abi::Ink>`
37-
= note: required for `Result<ContractRef, contract::Error>` to implement `ConstructorReturnType<ContractRef, ink::abi::Ink>`
37+
= note: required for `Result<ContractRefFor, contract::Error>` to implement `ConstructorReturnType<ContractRefFor, ink::abi::Ink>`
3838
note: required by a bound in `CreateBuilder::<E, ContractRef, Limits, Args, Unset<ReturnType<()>>, Abi>::returns`
3939
--> $WORKSPACE/crates/env/src/call/create_builder.rs
4040
|

integration-tests/all-abi/events/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ pub mod events {
424424
) -> E2EResult<()> {
425425
// given
426426
let init_value = false;
427-
let mut constructor = EventsRef::<ink::abi::Ink>::new(init_value);
427+
let mut constructor = EventsRef::new(init_value);
428428
let contract = client
429429
.instantiate("events", &ink_e2e::alice(), &mut constructor)
430430
.submit()
@@ -487,7 +487,7 @@ pub mod events {
487487
) -> E2EResult<()> {
488488
// given
489489
let init_value = false;
490-
let mut constructor = EventsRef::<ink::abi::Ink>::new(init_value);
490+
let mut constructor = EventsRef::new(init_value);
491491
let contract = client
492492
.instantiate("events", &ink_e2e::alice(), &mut constructor)
493493
.submit()
@@ -574,7 +574,7 @@ pub mod events {
574574
) -> E2EResult<()> {
575575
// given
576576
let init_value = false;
577-
let mut constructor = EventsRef::<ink::abi::Ink>::new(init_value);
577+
let mut constructor = EventsRef::new(init_value);
578578
let contract = client
579579
.instantiate("events", &ink_e2e::alice(), &mut constructor)
580580
.submit()
@@ -649,7 +649,7 @@ pub mod events {
649649
) -> E2EResult<()> {
650650
// given
651651
let init_value = false;
652-
let mut constructor = EventsRef::<ink::abi::Ink>::new(init_value);
652+
let mut constructor = EventsRef::new(init_value);
653653
let contract = client
654654
.instantiate("events", &ink_e2e::alice(), &mut constructor)
655655
.submit()

0 commit comments

Comments
 (0)