difftreelog
Merge pull request #569 from UniqueNetwork/feature/evm-conditional-inheritance
in: master
11 files changed
crates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth42 pascal_call_name: Ident,42 pascal_call_name: Ident,43 snake_call_name: Ident,43 snake_call_name: Ident,44 via: Option<(Type, Ident)>,44 via: Option<(Type, Ident)>,45 condition: Option<Expr>,45}46}46impl Is {47impl Is {47 fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {48 fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {64 generics: &proc_macro2::TokenStream,65 generics: &proc_macro2::TokenStream,65 ) -> proc_macro2::TokenStream {66 ) -> proc_macro2::TokenStream {66 let pascal_call_name = &self.pascal_call_name;67 let pascal_call_name = &self.pascal_call_name;68 let condition = self.condition.as_ref().map(|condition| {69 quote! {70 (#condition) &&71 }72 });67 quote! {73 quote! {68 <#pascal_call_name #generics>::supports_interface(interface_id)74 #condition <#pascal_call_name #generics>::supports_interface(this, interface_id)69 }75 }70 }76 }717793 .as_ref()99 .as_ref()94 .map(|(_, i)| quote! {.#i()})100 .map(|(_, i)| quote! {.#i()})95 .unwrap_or_default();101 .unwrap_or_default();102 let condition = self.condition.as_ref().map(|condition| {103 quote! {104 if ({let this = &self; (#condition)})105 }106 });96 quote! {107 quote! {97 #call_name::#name(call) => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {108 #call_name::#name(call) #condition => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {98 call,109 call,99 caller: c.caller,110 caller: c.caller,100 value: c.value,111 value: c.value,139 let name = input.parse::<Ident>()?;150 let name = input.parse::<Ident>()?;140 let lookahead = input.lookahead1();151 let lookahead = input.lookahead1();152153 let mut condition: Option<Expr> = None;141 let via = if lookahead.peek(syn::token::Paren) {154 let mut via: Option<(Type, Ident)> = None;155156 if lookahead.peek(syn::token::Paren) {142 let contents;157 let contents;143 parenthesized!(contents in input);158 parenthesized!(contents in input);159 let input = contents;160161 while !input.is_empty() {162 let lookahead = input.lookahead1();163 if lookahead.peek(Token![if]) {164 input.parse::<Token![if]>()?;165 let contents;166 parenthesized!(contents in input);167 let contents = contents.parse::<Expr>()?;168169 if condition.replace(contents).is_some() {170 return Err(syn::Error::new(input.span(), "condition is already set"));171 }172 } else if lookahead.peek(kw::via) {173 input.parse::<kw::via>()?;174 let contents;175 parenthesized!(contents in input);176144 let method = contents.parse::<Ident>()?;177 let method = contents.parse::<Ident>()?;145 contents.parse::<Token![,]>()?;178 contents.parse::<kw::returns>()?;146 let ty = contents.parse::<Type>()?;179 let ty = contents.parse::<Type>()?;180147 Some((ty, method))181 if via.replace((ty, method)).is_some() {182 return Err(syn::Error::new(input.span(), "via is already set"));183 }184 } else {185 return Err(lookahead.error());186 }187188 if input.peek(Token![,]) {189 input.parse::<Token![,]>()?;190 } else if !input.is_empty() {191 return Err(syn::Error::new(input.span(), "expected end"));192 }193 }148 } else if lookahead.peek(Token![,]) {194 } else if lookahead.peek(Token![,]) || input.is_empty() {149 None195 // Pass150 } else if input.is_empty() {151 None152 } else {196 } else {153 return Err(lookahead.error());197 return Err(lookahead.error());154 };198 };157 snake_call_name: pascal_ident_to_snake_call(&name),201 snake_call_name: pascal_ident_to_snake_call(&name),158 name,202 name,159 via,203 via,204 condition,160 });205 });161 if input.peek(Token![,]) {206 if input.peek(Token![,]) {162 input.parse::<Token![,]>()?;207 input.parse::<Token![,]>()?;495 syn::custom_keyword!(weight);540 syn::custom_keyword!(weight);496541497 syn::custom_keyword!(via);542 syn::custom_keyword!(via);543 syn::custom_keyword!(returns);498 syn::custom_keyword!(name);544 syn::custom_keyword!(name);499 syn::custom_keyword!(is);545 syn::custom_keyword!(is);500 syn::custom_keyword!(inline_is);546 syn::custom_keyword!(inline_is);996 #(#inline_interface_id)*1042 #(#inline_interface_id)*997 u32::to_be_bytes(interface_id)1043 u32::to_be_bytes(interface_id)998 }1044 }999 /// Is this contract implements specified ERC165 selector1000 pub fn supports_interface(interface_id: ::evm_coder::types::bytes4) -> bool {1001 interface_id != u32::to_be_bytes(0xffffff) && (1002 interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||1003 interface_id == Self::interface_id()1004 #(1005 || #supports_interface1006 )*1007 )1008 }1009 /// Generate solidity definitions for methods described in this interface1045 /// Generate solidity definitions for methods described in this interface1010 pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {1046 pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {1011 use evm_coder::solidity::*;1047 use evm_coder::solidity::*;1024 )*),1060 )*),1025 };1061 };102610621027 let mut out = string::new();1063 let mut out = ::evm_coder::types::string::new();1028 if #solidity_name.starts_with("Inline") {1064 if #solidity_name.starts_with("Inline") {1029 out.push_str("/// @dev inlined interface\n");1065 out.push_str("/// @dev inlined interface\n");1030 }1066 }1062 return Ok(None);1098 return Ok(None);1063 }1099 }1064 }1100 }1065 impl #generics ::evm_coder::Weighted for #call_name #gen_ref1101 impl #generics #call_name #gen_ref1102 #gen_where1103 {1104 /// Is this contract implements specified ERC165 selector1105 pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::bytes4) -> bool {1106 interface_id != u32::to_be_bytes(0xffffff) && (1107 interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||1108 interface_id == Self::interface_id()1109 #(1110 || #supports_interface1111 )*1112 )1113 }1114 }1115 impl #generics ::evm_coder::Weighted for #call_name #gen_ref1066 #gen_where1116 #gen_where1067 {1117 {1068 #[allow(unused_variables)]1118 #[allow(unused_variables)]1091 )*1141 )*1092 #call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {1142 #call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {1093 let mut writer = ::evm_coder::abi::AbiWriter::default();1143 let mut writer = ::evm_coder::abi::AbiWriter::default();1094 writer.bool(&<#call_name #gen_ref>::supports_interface(interface_id));1144 writer.bool(&<#call_name #gen_ref>::supports_interface(self, interface_id));1095 return Ok(writer.into());1145 return Ok(writer.into());1096 }1146 }1097 _ => {},1147 _ => {},1101 #(1151 #(1102 #call_variants_this,1152 #call_variants_this,1103 )*1153 )*1104 _ => unreachable!()1154 _ => Err(::evm_coder::execution::Error::from("method is not available").into()),1105 }1155 }1106 }1156 }1107 }1157 }crates/evm-coder/src/abi.rsdiffbeforeafterboth313 /// Finish writer, concatenating all internal buffers313 /// Finish writer, concatenating all internal buffers314 pub fn finish(mut self) -> Vec<u8> {314 pub fn finish(mut self) -> Vec<u8> {315 for (static_offset, part) in self.dynamic_part {315 for (static_offset, part) in self.dynamic_part {316 let part_offset = self.static_part.len() - self.had_call.then(|| 4).unwrap_or(0);316 let part_offset = self.static_part.len() - if self.had_call { 4 } else { 0 };317317318 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);318 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);319 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()319 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()crates/evm-coder/src/lib.rsdiffbeforeafterboth74/// #[solidity_interface(name = MyContract, is(SuperContract), inline_is(InlineContract))]74/// #[solidity_interface(name = MyContract, is(SuperContract), inline_is(InlineContract))]75/// impl Contract {75/// impl Contract {76/// /// Multiply two numbers76/// /// Multiply two numbers77/// /// @param a First number77/// /// @param a First number78/// /// @param b Second number78/// /// @param b Second number79/// /// @return uint32 Product of two passed numbers79/// /// @return uint32 Product of two passed numbers80/// /// @dev This function returns error in case of overflow80/// /// @dev This function returns error in case of overflow81/// #[weight(200 + a + b)]81/// #[weight(200 + a + b)]82/// #[solidity_interface(rename_selector = "mul")]82/// #[solidity_interface(rename_selector = "mul")]83/// fn mul(&mut self, a: uint32, b: uint32) -> Result<uint32> {83/// fn mul(&mut self, a: uint32, b: uint32) -> Result<uint32> {crates/evm-coder/tests/conditional_is.rsdiffbeforeafterbothno changes
crates/evm-coder/tests/generics.rsdiffbeforeafterboth17use std::marker::PhantomData;17use std::marker::PhantomData;18use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};18use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};191920struct Generic<T>(PhantomData<T>);20pub struct Generic<T>(PhantomData<T>);212122#[solidity_interface(name = GenericIs)]22#[solidity_interface(name = GenericIs)]23impl<T> Generic<T> {23impl<T> Generic<T> {crates/evm-coder/tests/random.rsdiffbeforeafterboth181819use evm_coder::{ToLog, execution::Result, solidity_interface, types::*, solidity, weight};19use evm_coder::{ToLog, execution::Result, solidity_interface, types::*, solidity, weight};202021struct Impls;21pub struct Impls;222223#[solidity_interface(name = OurInterface)]23#[solidity_interface(name = OurInterface)]24impl Impls {24impl Impls {crates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth161617use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};17use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};181819struct ERC20;19pub struct ERC20;202021#[solidity_interface(name = ERC20)]21#[solidity_interface(name = ERC20)]22impl ERC20 {22impl ERC20 {pallets/common/src/erc.rsdiffbeforeafterboth406 true => {406 true => {407 let mut bv = OwnerRestrictedSet::new();407 let mut bv = OwnerRestrictedSet::new();408 for i in collections {408 for i in collections {409 bv.try_insert(crate::eth::map_eth_to_id(&i).ok_or(Error::Revert(409 bv.try_insert(crate::eth::map_eth_to_id(&i).ok_or_else(|| {410 "Can't convert address into collection id".into(),410 Error::Revert("Can't convert address into collection id".into())411 ))?)411 })?)412 .map_err(|_| "too many collections")?;412 .map_err(|_| "too many collections")?;413 }413 }414 let mut nesting = permissions.nesting().clone();414 let mut nesting = permissions.nesting().clone();pallets/fungible/src/erc.rsdiffbeforeafterboth199 ERC20,199 ERC20,200 ERC20Mintable,200 ERC20Mintable,201 ERC20UniqueExtensions,201 ERC20UniqueExtensions,202 Collection(common_mut, CollectionHandle<T>),202 Collection(via(common_mut returns CollectionHandle<T>)),203 )203 )204)]204)]205impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}205impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}pallets/nonfungible/src/erc.rsdiffbeforeafterboth736 ERC721UniqueExtensions,736 ERC721UniqueExtensions,737 ERC721Mintable,737 ERC721Mintable,738 ERC721Burnable,738 ERC721Burnable,739 Collection(common_mut, CollectionHandle<T>),739 Collection(via(common_mut returns CollectionHandle<T>)),740 TokenProperties,740 TokenProperties,741 )741 )742)]742)]pallets/refungible/src/erc.rsdiffbeforeafterboth785 ERC721UniqueExtensions,785 ERC721UniqueExtensions,786 ERC721Mintable,786 ERC721Mintable,787 ERC721Burnable,787 ERC721Burnable,788 Collection(common_mut, CollectionHandle<T>),788 Collection(via(common_mut returns CollectionHandle<T>)),789 TokenProperties,789 TokenProperties,790 )790 )791)]791)]