Description
Questions
"ink::trait_definition" may not design completely for many case.
Description
In my view, the "ink::trait_definition" is same as the interface
part in solidity, is a way to be agreed with different contracts, third parity, and the basic element for contract specification like "ERC20", "ERC721" or else.
But now, the "ink::trait_definition" just shows some case in example. When I try to use the "ink::trait_definition" in other case, meet many problems.
- when split the "ink::trait_definition" part to another crate, it would meet problems. for example:
-
put a "ink::trait_definition" in an independent crate, and the "ink::trait_definition" is in the
mod
which is modified byink::contract
:
This is the example link: https://github.com/patractlabs/metis/blob/master/traits/access/ownership/lib.rs
First, I think a specification should include the "Event" part, like ERC20 contains the spec for events. For the third part using the event to mark something happen. But currently,#[ink(event)]
must in theink::contract
mod.
But I know putting theink::contract
onmod
, when other contract need to use this contract, current contract crate should be used in featureink-as-dependency
. For this example: https://github.com/patractlabs/metis/blob/master/impls/token/erc20/Cargo.toml. (erc20-trait part)
However when usingink-as-dependency
, the#[ink(event)]
would be ignore and could not be used in other contracts. If not usingink-as-dependency
, the contract could not be compiled. I think the event should be part of specification, thus, the event should be some part of "ink::trait_definition" or could be independent withink::contract
, or desgin some "spec event" for this case.
And Second, if theink::contract
mod do not have the part of#[ink(storage)]
,[ink(constructor)]
and#[ink(message)]
, it could not be compiled. Thus I addpub struct Phantom;
in abrove example just for dompilation.
I think if I just define an interface, I should could compile "ink::trait_definition" directly, do not need other hack operation. -
If do not put "ink::trait_definition" in the mod which is modified by
ink::contract
This is the example link: https://github.com/patractlabs/metis/blob/master/traits/access/ownership/lib.rs
I define the#[ink::trait_definition]
in the lib.rs directly. It would meet two problem:- This crate could only be compiled when using
cargo +nighlty build
command, and could not be compiled withcargo +nighlty contract build
. Ifink!
choosescargo-contract
as the tool to compile contract, I think thecargo-contract
should be able to use in this case, either provides another subcommand likecargo +nighlty contract trait build
, or supports#[ink::trait_definition]
could be compiled without[ink(constructor)]
directly. - If without
[ink(constructor)]
, current crate could not write#[ink(event)]
, for the event must be in the modink::contract
now.
- This crate could only be compiled when using
-
The message which in the "ink::trait_definition" is strongly correlated with the Trait name, which would cause some problem:
- The "ink::trait_definition" could not do type define like:
use Trait as SomeOtherName
.
e.g. If I define a Trait Erc20 in a crate and in another crate, I want to implement theErc20 Trait
for astruct Erc20
, then in case the conflicted name, I try to doHowever the selector is calculated byuse erc20_trait::erc20::Erc20 as Erc20Trait;
TraitName,MessageName
, thus the source selector isErc20,transfer
, and in the implementation part, it'sErc20Trait,transfer
, so it cause the compilation error. - I notice the "name" for "messages"/"constructors" is an array in metadata, not a value.
I think this design is related to Trait system which just in rust. Like If someone define a trait "IErc20" which contains a message "transfer" aand define another trait "NeedTransfer" which contains same name message "transfer" too. And the two traits are implemented for one contract, then the selector should belong to different trait. So that the name is designed in an array.
But the array is not friendly for 3rd parity tool, like just for polkadot.js'scontract-api
, when I call a message, just could usecontract.query['erc20,balanceOf']
, and could not to do the call likeweb3.js
do, loading an abi to generate function. In Redspot, we plan to design a wrapper to changecontract.query['erc20,balanceOf']
tocontract.erc20.balanceOf
, conventing the,
to.
. However in this way it's hard to add type hint for typescript. And in anther language sdk, we plan to do this operation as well.
But all in all, I think desgin an array for this name part and generated by this name may not a good choose. I think we could design a namespace first, to express different Trait, like "IErc20" and "NeedTransfer", and this name should not be binding with the source name(to support type define like "as"). The final level for the namespace is the message function name. Thus the "name" in metadata could like:and{ "name": { "IErc20": "transfer" } }
This modle is friendly for 3rd parity to generate the type info, and may could do some mapping for the Trait name. And if the contract define a message name same as the Trait name, it's not conflicted, for example:{ "name": { "NeedTransfer": "transfer" } }
contract define a function name "IErc20":
and another trait message generates like:{ "name": "IErc20" }
the contract is implemented by a Trait "IErc20", and this Trait provide a message "transfer"
{ "name": { "IErc20": "transfer" } }
- The "ink::trait_definition" could not do type define like:
-