difftreelog
feat define new execution traits
in: master
5 files changed
crates/evm-coder-macros/src/lib.rsdiffbeforeafterboth127}127}128128129// Gets T out of Result<T>129// Gets T out of Result<T>130fn parse_result_ok(ty: &Type) -> syn::Result<&Ident> {130fn parse_result_ok(ty: &Type) -> syn::Result<&Type> {131 let path = parse_path(ty)?;131 let path = parse_path(ty)?;132 let segment = parse_path_segment(path)?;132 let segment = parse_path_segment(path)?;133133160 }160 }161 };161 };162162163 parse_ident_from_type(ty)163 Ok(ty)164}164}165165166fn pascal_ident_to_call(ident: &Ident) -> Ident {166fn pascal_ident_to_call(ident: &Ident) -> Ident {184 Ident::new(&name, ident.span())184 Ident::new(&name, ident.span())185}185}186187fn format_ty(ty: &Ident) -> String {188 if ty == "string" {189 format!("{} memory", ty)190 } else {191 ty.to_string()192 }193}194186195#[proc_macro_attribute]187#[proc_macro_attribute]196pub fn solidity_interface(args: TokenStream, stream: TokenStream) -> TokenStream {188pub fn solidity_interface(args: TokenStream, stream: TokenStream) -> TokenStream {crates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth4use darling::FromMeta;4use darling::FromMeta;5use inflector::cases;5use inflector::cases;6use std::fmt::Write;6use std::fmt::Write;7use syn::{7use syn::{FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem, TraitItemMethod, Type, Visibility, spanned::Spanned};8 FnArg, Ident, ItemTrait, Meta, NestedMeta, PatType, Path, ReturnType, TraitItem,9 TraitItemMethod, Visibility, spanned::Spanned,10};11812use crate::{9use crate::{13 fn_selector_str, format_ty, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type,10 fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type,14 parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,11 parse_result_ok, pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,15 snake_ident_to_screaming,12 snake_ident_to_screaming,16};13};68 let snake_call_name = &self.snake_call_name;65 let snake_call_name = &self.snake_call_name;69 let pascal_call_name = &self.pascal_call_name;66 let pascal_call_name = &self.pascal_call_name;70 quote! {67 quote! {71 fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> ::core::result::Result<::evm_coder::abi::AbiWriter, Self::Error>;68 fn #snake_call_name(&mut self, c: Msg<#pascal_call_name>) -> Result<::evm_coder::abi::AbiWriter>;72 }69 }73 }70 }7471174 }171 }175 }172 }176177 fn solidity_def(&self) -> String {178 assert!(!self.is_special());179 format!("{} {}", format_ty(&self.ty), self.name)180 }181}173}182174183#[derive(PartialEq)]175#[derive(PartialEq)]197 args: Vec<MethodArg>,189 args: Vec<MethodArg>,198 has_normal_args: bool,190 has_normal_args: bool,199 mutability: Mutability,191 mutability: Mutability,200 result: Ident,192 result: Type,201}193}202impl Method {194impl Method {203 fn try_from(value: &TraitItemMethod) -> syn::Result<Self> {195 fn try_from(value: &TraitItemMethod) -> syn::Result<Self> {392 }384 }393 }385 }394395 fn solidity_def(&self) -> String {396 let mut out = format!("function {}(", self.camel_name);397 for (i, arg) in self.args.iter().filter(|a| !a.is_special()).enumerate() {398 if i != 0 {399 out.push_str(", ");400 }401 out.push_str(&arg.solidity_def());402 }403 out.push(')');404 match self.mutability {405 Mutability::Mutable => {}406 Mutability::View => write!(out, " view").unwrap(),407 Mutability::Pure => write!(out, " pure").unwrap(),408 }409 if self.result != "void" {410 write!(out, " returns ({})", format_ty(&self.result)).unwrap();411 }412 out.push(';');413 out414 }415}386}416387417pub struct SolidityInterface {388pub struct SolidityInterface {423}394}424impl SolidityInterface {395impl SolidityInterface {425 pub fn try_from(info: InterfaceInfo, value: &ItemTrait) -> syn::Result<Self> {396 pub fn try_from(info: InterfaceInfo, value: &ItemTrait) -> syn::Result<Self> {426 let mut found_error = false;427 let mut methods = Vec::new();397 let mut methods = Vec::new();428398429 for item in &value.items {399 for item in &value.items {430 match item {400 match item {431 TraitItem::Type(ty) => {432 if ty.ident == "Error" {433 found_error = true;434 }435 }436 TraitItem::Method(method) => methods.push(Method::try_from(method)?),401 TraitItem::Method(method) => methods.push(Method::try_from(method)?),437 _ => {}402 _ => {}438 }403 }439 }404 }440 if !found_error {441 return Err(syn::Error::new(442 value.span(),443 "expected associated type called Error, which should implement From<&str>",444 ));445 }446 Ok(Self {405 Ok(Self {447 vis: value.vis.clone(),406 vis: value.vis.clone(),448 name: value.ident.clone(),407 name: value.ident.clone(),508 #call_sub,467 #call_sub,509 )*468 )*510 }469 }511 impl #call_name {470 impl #call_name {471 #(472 #consts473 )*474 pub const fn interface_id() -> u32 {475 let mut interface_id = 0;476 #(#interface_id)*477 #(#inline_interface_id)*478 interface_id479 }480 pub fn supports_interface(interface_id: u32) -> bool {481 interface_id != 0xffffff && (482 interface_id == Self::interface_id()483 #(484 || #supports_interface485 )*486 )487 }488 }512 #(489 impl ::evm_coder::Call for #call_name {513 #consts514 )*515 pub fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::abi::Result<Option<Self>> {490 fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {516 use ::evm_coder::abi::AbiRead;491 use ::evm_coder::abi::AbiRead;517 match method_id {492 match method_id {518 #(493 #(525 )else*500 )else*526 return Ok(None);501 return Ok(None);527 }502 }528 pub const fn interface_id() -> u32 {503 }529 let mut interface_id = 0;530 #(#interface_id)*531 #(#inline_interface_id)*532 interface_id533 }534 pub fn supports_interface(interface_id: u32) -> bool {535 interface_id != 0xffffff && (536 interface_id == Self::interface_id()537 #(538 || #supports_interface539 )*540 )541 }542 }543 #vis trait #name {504 #vis trait #name {544 #(505 #(545 #items506 #items546 )*507 )*547 #(508 #(548 #call_inner509 #call_inner549 )*510 )*511 }512 impl<T> ::evm_coder::Callable for T where T: #name {513 type Call = #call_name;550 #[allow(unreachable_code)] // In case of no inner calls514 #[allow(unreachable_code)] // In case of no inner calls551 fn call(&mut self, c: Msg<#call_name>) -> ::core::result::Result<::evm_coder::abi::AbiWriter, Self::Error> {515 fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> {552 use ::evm_coder::abi::AbiWrite;516 use ::evm_coder::abi::AbiWrite;553 type InternalCall = #call_name;517 type InternalCall = #call_name;554 match c.call {518 match c.call {566 }530 }567 Ok(writer)531 Ok(writer)568 }532 }569 }533 }570 }534 }571 }535 }572}536}crates/evm-coder/Cargo.tomldiffbeforeafterboth8primitive-types = { version = "0.9", default-features = false }8primitive-types = { version = "0.9", default-features = false }9hex-literal = "0.3"9hex-literal = "0.3"10ethereum = { version = "0.7.1", default-features = false }10ethereum = { version = "0.7.1", default-features = false }11evm-core = { git = "https://github.com/usetech-llc/evm.git", branch="precompile-output-parachain" }12impl-trait-for-tuples = "0.2.1"111312[dev-dependencies]14[dev-dependencies]13hex = "0.4.3"15hex = "0.4.3"crates/evm-coder/src/lib.rsdiffbeforeafterboth2#[cfg(not(feature = "std"))]2#[cfg(not(feature = "std"))]3extern crate alloc;3extern crate alloc;445use abi::{AbiReader, AbiWriter};5pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog};6pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog};6pub mod abi;7pub mod abi;7pub mod events;8pub mod events;8pub use events::ToLog;9pub use events::ToLog;10pub mod execution;11pub mod solidity;91210/// Solidity type definitions13/// Solidity type definitions11pub mod types {14pub mod types {50 }53 }51}54}5556pub trait Call: Sized {57 fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;58}5960pub trait Callable {61 type Call: Call;62 fn call(&mut self, call: types::Msg<Self::Call>) -> execution::Result<AbiWriter>;63}526453#[cfg(test)]65#[cfg(test)]54mod tests {66mod tests {crates/evm-coder/tests/a.rsdiffbeforeafterboth1#![allow(dead_code)] // This test only checks that macros is not panicking1#![allow(dead_code)] // This test only checks that macros is not panicking223use evm_coder::{solidity_interface, types::*, ToLog};3use evm_coder::{solidity_interface, types::*, ToLog, execution::Result};4use evm_coder_macros::solidity;4use evm_coder_macros::solidity;556#[solidity_interface]6#[solidity_interface]7trait OurInterface {7trait OurInterface {8 type Error;9 fn fn_a(&self, input: uint256) -> Result<bool, Self::Error>;8 fn fn_a(&self, input: uint256) -> Result<bool>;10}9}111012#[solidity_interface]11#[solidity_interface]13trait OurInterface1 {12trait OurInterface1 {14 type Error;15 fn fn_b(&self, input: uint128) -> Result<uint32, Self::Error>;13 fn fn_b(&self, input: uint128) -> Result<uint32>;16}14}171518#[solidity_interface(is(OurInterface), inline_is(OurInterface1), events(ERC721Log))]16#[solidity_interface(is(OurInterface), inline_is(OurInterface1), events(ERC721Log))]19trait OurInterface2 {17trait OurInterface2 {20 type Error;21 #[solidity(rename_selector = "fnK")]18 #[solidity(rename_selector = "fnK")]22 fn fn_c(&self, input: uint32) -> Result<uint8, Self::Error>;19 fn fn_c(&self, input: uint32) -> Result<uint8>;23 fn fn_d(&self, value: uint32) -> Result<uint32, Self::Error>;20 fn fn_d(&self, value: uint32) -> Result<uint32>;242125 fn caller_sensitive(&self, caller: caller) -> Result<uint8, Self::Error>;22 fn caller_sensitive(&self, caller: caller) -> Result<uint8>;26 fn payable(&mut self, value: value) -> Result<uint8, Self::Error>;23 fn payable(&mut self, value: value) -> Result<uint8>;27}24}282529#[derive(ToLog)]26#[derive(ToLog)]444145#[solidity_interface]42#[solidity_interface]46trait ERC20 {43trait ERC20 {47 type Error;4849 fn decimals(&self) -> Result<uint8, Self::Error>;44 fn decimals(&self) -> Result<uint8>;50 fn balance_of(&self, owner: address) -> Result<uint256, Self::Error>;45 fn balance_of(&self, owner: address) -> Result<uint256>;51 fn transfer(46 fn transfer(&mut self, caller: caller, to: address, value: uint256) -> Result<bool>;52 &mut self,53 caller: caller,54 to: address,55 value: uint256,56 ) -> Result<bool, Self::Error>;57 fn transfer_from(47 fn transfer_from(58 &mut self,48 &mut self,59 caller: caller,49 caller: caller,60 from: address,50 from: address,61 to: address,51 to: address,62 value: uint256,52 value: uint256,63 ) -> Result<bool, Self::Error>;53 ) -> Result<bool>;64 fn approve(54 fn approve(&mut self, caller: caller, spender: address, value: uint256) -> Result<bool>;65 &mut self,66 caller: caller,67 spender: address,68 value: uint256,69 ) -> Result<bool, Self::Error>;70 fn allowance(&self, owner: address, spender: address) -> Result<uint256, Self::Error>;55 fn allowance(&self, owner: address, spender: address) -> Result<uint256>;71}56}7257