--- a/crates/evm-coder-macros/src/lib.rs +++ b/crates/evm-coder-macros/src/lib.rs @@ -127,7 +127,7 @@ } // Gets T out of Result -fn parse_result_ok(ty: &Type) -> syn::Result<&Ident> { +fn parse_result_ok(ty: &Type) -> syn::Result<&Type> { let path = parse_path(ty)?; let segment = parse_path_segment(path)?; @@ -160,7 +160,7 @@ } }; - parse_ident_from_type(ty) + Ok(ty) } fn pascal_ident_to_call(ident: &Ident) -> Ident { @@ -182,14 +182,6 @@ let name = cases::snakecase::to_snake_case(&name); let name = format!("call_{}", name); Ident::new(&name, ident.span()) -} - -fn format_ty(ty: &Ident) -> String { - if ty == "string" { - format!("{} memory", ty) - } else { - ty.to_string() - } } #[proc_macro_attribute] --- a/crates/evm-coder-macros/src/solidity_interface.rs +++ b/crates/evm-coder-macros/src/solidity_interface.rs @@ -4,13 +4,10 @@ use darling::FromMeta; use inflector::cases; use std::fmt::Write; -use syn::{ - FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem, - TraitItemMethod, Visibility, spanned::Spanned, -}; +use syn::{FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem, TraitItemMethod, Type, Visibility, spanned::Spanned}; use crate::{ - fn_selector_str, format_ty, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type, + fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type, parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal, snake_ident_to_screaming, }; @@ -68,7 +65,7 @@ let snake_call_name = &self.snake_call_name; let pascal_call_name = &self.pascal_call_name; quote! { - fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> ::core::result::Result<::evm_coder::abi::AbiWriter, Self::Error>; + fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> Result<::evm_coder::abi::AbiWriter>; } } @@ -173,11 +170,6 @@ } } } - - fn solidity_def(&self) -> String { - assert!(!self.is_special()); - format!("{} {}", format_ty(&self.ty), self.name) - } } #[derive(PartialEq)] @@ -197,7 +189,7 @@ args: Vec, has_normal_args: bool, mutability: Mutability, - result: Ident, + result: Type, } impl Method { fn try_from(value: &TraitItemMethod) -> syn::Result { @@ -388,29 +380,8 @@ )* )?; (&result).abi_write(&mut writer); - } - } - } - - fn solidity_def(&self) -> String { - let mut out = format!("function {}(", self.camel_name); - for (i, arg) in self.args.iter().filter(|a| !a.is_special()).enumerate() { - if i != 0 { - out.push_str(", "); } - out.push_str(&arg.solidity_def()); - } - out.push(')'); - match self.mutability { - Mutability::Mutable => {} - Mutability::View => write!(out, " view").unwrap(), - Mutability::Pure => write!(out, " pure").unwrap(), } - if self.result != "void" { - write!(out, " returns ({})", format_ty(&self.result)).unwrap(); - } - out.push(';'); - out } } @@ -423,26 +394,14 @@ } impl SolidityInterface { pub fn try_from(info: InterfaceInfo, value: &ItemTrait) -> syn::Result { - let mut found_error = false; let mut methods = Vec::new(); for item in &value.items { match item { - TraitItem::Type(ty) => { - if ty.ident == "Error" { - found_error = true; - } - } TraitItem::Method(method) => methods.push(Method::try_from(method)?), _ => {} } } - if !found_error { - return Err(syn::Error::new( - value.span(), - "expected associated type called Error, which should implement From<&str>", - )); - } Ok(Self { vis: value.vis.clone(), name: value.ident.clone(), @@ -512,19 +471,6 @@ #( #consts )* - pub fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::abi::Result> { - use ::evm_coder::abi::AbiRead; - match method_id { - #( - #parsers, - )* - _ => {}, - } - #( - #call_parse - )else* - return Ok(None); - } pub const fn interface_id() -> u32 { let mut interface_id = 0; #(#interface_id)* @@ -540,6 +486,21 @@ ) } } + impl ::evm_coder::Call for #call_name { + fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result> { + use ::evm_coder::abi::AbiRead; + match method_id { + #( + #parsers, + )* + _ => {}, + } + #( + #call_parse + )else* + return Ok(None); + } + } #vis trait #name { #( #items @@ -547,8 +508,11 @@ #( #call_inner )* + } + impl ::evm_coder::Callable for T where T: #name { + type Call = #call_name; #[allow(unreachable_code)] // In case of no inner calls - fn call(&mut self, c: Msg<#call_name>) -> ::core::result::Result<::evm_coder::abi::AbiWriter, Self::Error> { + fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> { use ::evm_coder::abi::AbiWrite; type InternalCall = #call_name; match c.call { @@ -566,7 +530,7 @@ } Ok(writer) } - } + } } } } --- a/crates/evm-coder/Cargo.toml +++ b/crates/evm-coder/Cargo.toml @@ -8,6 +8,8 @@ primitive-types = { version = "0.9", default-features = false } hex-literal = "0.3" ethereum = { version = "0.7.1", default-features = false } +evm-core = { git = "https://github.com/usetech-llc/evm.git", branch="precompile-output-parachain" } +impl-trait-for-tuples = "0.2.1" [dev-dependencies] hex = "0.4.3" --- a/crates/evm-coder/src/lib.rs +++ b/crates/evm-coder/src/lib.rs @@ -2,10 +2,13 @@ #[cfg(not(feature = "std"))] extern crate alloc; +use abi::{AbiReader, AbiWriter}; pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog}; pub mod abi; pub mod events; pub use events::ToLog; +pub mod execution; +pub mod solidity; /// Solidity type definitions pub mod types { @@ -50,6 +53,15 @@ } } +pub trait Call: Sized { + fn parse(selector: u32, input: &mut AbiReader) -> execution::Result>; +} + +pub trait Callable { + type Call: Call; + fn call(&mut self, call: types::Msg) -> execution::Result; +} + #[cfg(test)] mod tests { use super::*; --- a/crates/evm-coder/tests/a.rs +++ b/crates/evm-coder/tests/a.rs @@ -1,29 +1,26 @@ #![allow(dead_code)] // This test only checks that macros is not panicking -use evm_coder::{solidity_interface, types::*, ToLog}; +use evm_coder::{solidity_interface, types::*, ToLog, execution::Result}; use evm_coder_macros::solidity; #[solidity_interface] trait OurInterface { - type Error; - fn fn_a(&self, input: uint256) -> Result; + fn fn_a(&self, input: uint256) -> Result; } #[solidity_interface] trait OurInterface1 { - type Error; - fn fn_b(&self, input: uint128) -> Result; + fn fn_b(&self, input: uint128) -> Result; } #[solidity_interface(is(OurInterface), inline_is(OurInterface1), events(ERC721Log))] trait OurInterface2 { - type Error; #[solidity(rename_selector = "fnK")] - fn fn_c(&self, input: uint32) -> Result; - fn fn_d(&self, value: uint32) -> Result; + fn fn_c(&self, input: uint32) -> Result; + fn fn_d(&self, value: uint32) -> Result; - fn caller_sensitive(&self, caller: caller) -> Result; - fn payable(&mut self, value: value) -> Result; + fn caller_sensitive(&self, caller: caller) -> Result; + fn payable(&mut self, value: value) -> Result; } #[derive(ToLog)] @@ -44,28 +41,16 @@ #[solidity_interface] trait ERC20 { - type Error; - - fn decimals(&self) -> Result; - fn balance_of(&self, owner: address) -> Result; - fn transfer( - &mut self, - caller: caller, - to: address, - value: uint256, - ) -> Result; + fn decimals(&self) -> Result; + fn balance_of(&self, owner: address) -> Result; + fn transfer(&mut self, caller: caller, to: address, value: uint256) -> Result; fn transfer_from( &mut self, caller: caller, from: address, to: address, value: uint256, - ) -> Result; - fn approve( - &mut self, - caller: caller, - spender: address, - value: uint256, - ) -> Result; - fn allowance(&self, owner: address, spender: address) -> Result; + ) -> Result; + fn approve(&mut self, caller: caller, spender: address, value: uint256) -> Result; + fn allowance(&self, owner: address, spender: address) -> Result; }