From ae3e88161256b2e5ef77264a0ea9a19030a1949e Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Tue, 12 Oct 2021 16:55:56 +0000 Subject: [PATCH] feat: implicit implementation of ERC165 --- --- a/crates/evm-coder-macros/src/solidity_interface.rs +++ b/crates/evm-coder-macros/src/solidity_interface.rs @@ -672,6 +672,7 @@ quote! { #[derive(Debug)] pub enum #call_name { + ERC165Call(::evm_coder::ERC165Call), #( #calls, )* @@ -691,6 +692,7 @@ } pub fn supports_interface(interface_id: u32) -> bool { interface_id != 0xffffff && ( + interface_id == ::evm_coder::ERC165Call::INTERFACE_ID || interface_id == Self::interface_id() #( || #supports_interface @@ -702,7 +704,7 @@ use core::fmt::Write; let interface = SolidityInterface { name: #solidity_name, - is: &["Dummy", #( + is: &["Dummy", "ERC165", #( #solidity_is, )* #( #solidity_events_is, @@ -712,9 +714,9 @@ )*), }; if is_impl { - tc.collect("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\n".into()); + tc.collect("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ninterface ERC165 {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into()); } else { - tc.collect("// Common stubs holder\ninterface Dummy {\n}\n".into()); + tc.collect("// Common stubs holder\ninterface Dummy {\n}\ninterface ERC165 {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into()); } #( #solidity_generators @@ -737,6 +739,7 @@ fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result> { use ::evm_coder::abi::AbiRead; match method_id { + ::evm_coder::ERC165Call::INTERFACE_ID => return Ok(::evm_coder::ERC165Call::parse(method_id, reader)?.map(Self::ERC165Call)), #( #parsers, )* @@ -757,6 +760,11 @@ #( #call_variants, )* + InternalCall::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}) => { + let mut writer = ::evm_coder::abi::AbiWriter::default(); + writer.bool(&InternalCall::supports_interface(interface_id)); + return Ok(writer); + } _ => {}, } let mut writer = ::evm_coder::abi::AbiWriter::default(); --- a/crates/evm-coder/src/lib.rs +++ b/crates/evm-coder/src/lib.rs @@ -2,7 +2,7 @@ #[cfg(not(feature = "std"))] extern crate alloc; -use abi::{AbiReader, AbiWriter}; +use abi::{AbiRead, AbiReader, AbiWriter}; pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog}; pub mod abi; pub mod events; @@ -61,6 +61,29 @@ fn call(&mut self, call: types::Msg) -> execution::Result; } +/// Implementation is implicitly provided for all interfaces +/// +/// Note: no Callable implementation is provided +#[derive(Debug)] +pub enum ERC165Call { + SupportsInterface { interface_id: types::bytes4 }, +} + +impl ERC165Call { + pub const INTERFACE_ID: types::bytes4 = 0x01ffc9a7; +} + +impl Call for ERC165Call { + fn parse(selector: u32, input: &mut AbiReader) -> execution::Result> { + if selector != Self::INTERFACE_ID { + return Ok(None); + } + Ok(Some(Self::SupportsInterface { + interface_id: input.abi_read()?, + })) + } +} + #[macro_export] macro_rules! generate_stubgen { ($name:ident, $decl:ident, $is_impl:literal) => { -- gitstuff