difftreelog
feat implicit implementation of ERC165
in: master
2 files changed
crates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth--- 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<Option<Self>> {
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();
crates/evm-coder/src/lib.rsdiffbeforeafterboth1#![cfg_attr(not(feature = "std"), no_std)]2#[cfg(not(feature = "std"))]3extern crate alloc;45use abi::{AbiReader, AbiWriter};6pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog};7pub mod abi;8pub mod events;9pub use events::ToLog;10pub mod execution;11pub mod solidity;1213/// Solidity type definitions14pub mod types {15 #![allow(non_camel_case_types)]1617 #[cfg(not(feature = "std"))]18 use alloc::{vec::Vec};19 use primitive_types::{U256, H160, H256};2021 pub type address = H160;2223 pub type uint8 = u8;24 pub type uint16 = u16;25 pub type uint32 = u32;26 pub type uint64 = u64;27 pub type uint128 = u128;28 pub type uint256 = U256;2930 pub type bytes4 = u32;3132 pub type topic = H256;3334 #[cfg(not(feature = "std"))]35 pub type string = ::alloc::string::String;36 #[cfg(feature = "std")]37 pub type string = ::std::string::String;38 pub type bytes = Vec<u8>;3940 pub type void = ();4142 //#region Special types43 /// Makes function payable44 pub type value = U256;45 /// Makes function caller-sensitive46 pub type caller = address;47 //#endregion4849 pub struct Msg<C> {50 pub call: C,51 pub caller: H160,52 pub value: U256,53 }54}5556pub trait Call: Sized {57 fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;58}5960pub trait Callable<C: Call> {61 fn call(&mut self, call: types::Msg<C>) -> execution::Result<AbiWriter>;62}6364#[macro_export]65macro_rules! generate_stubgen {66 ($name:ident, $decl:ident, $is_impl:literal) => {67 #[test]68 #[ignore]69 fn $name() {70 use evm_coder::solidity::TypeCollector;71 let mut out = TypeCollector::new();72 $decl::generate_solidity_interface(&mut out, $is_impl);73 println!("=== SNIP START ===");74 println!("// SPDX-License-Identifier: OTHER");75 println!("// This code is automatically generated");76 println!();77 println!("pragma solidity >=0.8.0 <0.9.0;");78 println!();79 for b in out.finish() {80 println!("{}", b);81 }82 println!("=== SNIP END ===");83 }84 };85}8687#[cfg(test)]88mod tests {89 use super::*;9091 #[test]92 fn function_selector_generation() {93 assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);94 }9596 #[test]97 fn event_topic_generation() {98 assert_eq!(99 hex::encode(&event_topic!(Transfer(address, address, uint256))[..]),100 "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",101 );102 }103}1#![cfg_attr(not(feature = "std"), no_std)]2#[cfg(not(feature = "std"))]3extern crate alloc;45use abi::{AbiRead, AbiReader, AbiWriter};6pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog};7pub mod abi;8pub mod events;9pub use events::ToLog;10pub mod execution;11pub mod solidity;1213/// Solidity type definitions14pub mod types {15 #![allow(non_camel_case_types)]1617 #[cfg(not(feature = "std"))]18 use alloc::{vec::Vec};19 use primitive_types::{U256, H160, H256};2021 pub type address = H160;2223 pub type uint8 = u8;24 pub type uint16 = u16;25 pub type uint32 = u32;26 pub type uint64 = u64;27 pub type uint128 = u128;28 pub type uint256 = U256;2930 pub type bytes4 = u32;3132 pub type topic = H256;3334 #[cfg(not(feature = "std"))]35 pub type string = ::alloc::string::String;36 #[cfg(feature = "std")]37 pub type string = ::std::string::String;38 pub type bytes = Vec<u8>;3940 pub type void = ();4142 //#region Special types43 /// Makes function payable44 pub type value = U256;45 /// Makes function caller-sensitive46 pub type caller = address;47 //#endregion4849 pub struct Msg<C> {50 pub call: C,51 pub caller: H160,52 pub value: U256,53 }54}5556pub trait Call: Sized {57 fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;58}5960pub trait Callable<C: Call> {61 fn call(&mut self, call: types::Msg<C>) -> execution::Result<AbiWriter>;62}6364/// Implementation is implicitly provided for all interfaces65///66/// Note: no Callable implementation is provided67#[derive(Debug)]68pub enum ERC165Call {69 SupportsInterface { interface_id: types::bytes4 },70}7172impl ERC165Call {73 pub const INTERFACE_ID: types::bytes4 = 0x01ffc9a7;74}7576impl Call for ERC165Call {77 fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>> {78 if selector != Self::INTERFACE_ID {79 return Ok(None);80 }81 Ok(Some(Self::SupportsInterface {82 interface_id: input.abi_read()?,83 }))84 }85}8687#[macro_export]88macro_rules! generate_stubgen {89 ($name:ident, $decl:ident, $is_impl:literal) => {90 #[test]91 #[ignore]92 fn $name() {93 use evm_coder::solidity::TypeCollector;94 let mut out = TypeCollector::new();95 $decl::generate_solidity_interface(&mut out, $is_impl);96 println!("=== SNIP START ===");97 println!("// SPDX-License-Identifier: OTHER");98 println!("// This code is automatically generated");99 println!();100 println!("pragma solidity >=0.8.0 <0.9.0;");101 println!();102 for b in out.finish() {103 println!("{}", b);104 }105 println!("=== SNIP END ===");106 }107 };108}109110#[cfg(test)]111mod tests {112 use super::*;113114 #[test]115 fn function_selector_generation() {116 assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);117 }118119 #[test]120 fn event_topic_generation() {121 assert_eq!(122 hex::encode(&event_topic!(Transfer(address, address, uint256))[..]),123 "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",124 );125 }126}