ERC165
Component help Contract to creates a standard method to publish and detect what interfaces a smart contract implements.
The details of the ERC165 can see ERC165.
In ink!
, the message interface id is same to EVM, so we make a marco to help develop to impl the erc165.
#
Dependencyno additional dependency other than metis_lang
#
Usage ExampleFor example, a contract looks like:
impl Flipper { /// Creates a new flipper smart contract initialized with the given value. #[ink(constructor)] pub fn new(init_value: bool) -> Self { Self { value: init_value } }
/// Creates a new flipper smart contract initialized to `false`. #[ink(constructor)] pub fn default() -> Self { Self::new(Default::default()) }
/// Flips the current value of the Flipper's bool. #[ink(message)] pub fn flip(&mut self) { // logics }
/// Flips set the current value #[ink(message)] pub fn set(&mut self, value: bool) { // logics }
/// Returns the current value of the Flipper's bool. #[ink(message)] pub fn get(&self) -> bool { // logics } }
We can define a interface contains get
and set
message, so the supports_interface
should be:
impl Flipper { fn supports_interface(&self, interface_id: u32) -> bool { match interface_id { 0x633aa551_u32 ^ 0x2f865bd9_u32 => true, // get and set 0xe6113a8a_u32 => true, // supports_interface _ => false, } } }
Note if impl supports_interface
then also support the interface of erc165 self, so the 0xe6113a8a_u32
should also true.
The erc165 marco help us to impl the supports_interface
message:
#[metis::supports(interface(new, default), interface(flip, get))] impl Flipper { /// Return the contract is support the interface_id #[ink(message)] pub fn supports_interface(&self, interface_id: u32) -> bool { // _supports_interface gen by marco self._supports_interface(interface_id) } }
The code above is equivalent to:
impl Flipper { fn _supports_interface(&self, interface_id: u32) -> bool { const INIT_INTERFACE_ID: u32 = 0x9bae9d5e_u32 ^ 0xed4b9d1b_u32; const FLIP_INTERFACE_ID: u32 = 0x633aa551_u32 ^ 0x2f865bd9_u32;
match interface_id { INIT_INTERFACE_ID => true, // new and default FLIP_INTERFACE_ID => true, // flip get 0xe6113a8a_u32 => true, // supports_interface _ => false, } }
/// Return the contract is support the interface_id #[ink(message)] pub fn supports_interface(&self, interface_id: u32) -> bool { self._supports_interface(interface_id) } }
The marco will not make supports_interface
but a generic _supports_interface
for developer to impl supports_interface
.
The marco looks like:
#[metis::supports(interface(new, default), interface(flip, get))] impl Flipper {}
For a contract, it will support multi interfaces, so there is a array of interfaces, which contains the required message name.
Note: if use marco, the contract will support the
supports_interface
interface(0xe6113a8a_u32) auto.