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.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -313,7 +313,7 @@
/// Finish writer, concatenating all internal buffers
pub fn finish(mut self) -> Vec<u8> {
for (static_offset, part) in self.dynamic_part {
- let part_offset = self.static_part.len() - self.had_call.then(|| 4).unwrap_or(0);
+ let part_offset = self.static_part.len() - if self.had_call { 4 } else { 0 };
let encoded_dynamic_offset = usize::to_be_bytes(part_offset);
self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()
crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -74,10 +74,10 @@
/// #[solidity_interface(name = MyContract, is(SuperContract), inline_is(InlineContract))]
/// impl Contract {
/// /// Multiply two numbers
-/// /// @param a First number
-/// /// @param b Second number
-/// /// @return uint32 Product of two passed numbers
-/// /// @dev This function returns error in case of overflow
+/// /// @param a First number
+/// /// @param b Second number
+/// /// @return uint32 Product of two passed numbers
+/// /// @dev This function returns error in case of overflow
/// #[weight(200 + a + b)]
/// #[solidity_interface(rename_selector = "mul")]
/// fn mul(&mut self, a: uint32, b: uint32) -> Result<uint32> {
crates/evm-coder/tests/conditional_is.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/tests/conditional_is.rs
@@ -0,0 +1,44 @@
+use evm_coder::{types::*, solidity_interface, execution::Result, Call};
+
+pub struct Contract(bool);
+
+#[solidity_interface(name = A)]
+impl Contract {
+ fn method_a() -> Result<void> {
+ Ok(())
+ }
+}
+
+#[solidity_interface(name = B)]
+impl Contract {
+ fn method_b() -> Result<void> {
+ Ok(())
+ }
+}
+
+#[solidity_interface(name = Contract, is(
+ A(if(this.0)),
+ B(if(!this.0)),
+))]
+impl Contract {}
+
+#[test]
+fn conditional_erc165() {
+ assert!(ContractCall::supports_interface(
+ &Contract(true),
+ ACall::METHOD_A
+ ));
+ assert!(!ContractCall::supports_interface(
+ &Contract(false),
+ ACall::METHOD_A
+ ));
+
+ assert!(ContractCall::supports_interface(
+ &Contract(false),
+ BCall::METHOD_B
+ ));
+ assert!(!ContractCall::supports_interface(
+ &Contract(true),
+ BCall::METHOD_B
+ ));
+}
crates/evm-coder/tests/generics.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/generics.rs
+++ b/crates/evm-coder/tests/generics.rs
@@ -17,7 +17,7 @@
use std::marker::PhantomData;
use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};
-struct Generic<T>(PhantomData<T>);
+pub struct Generic<T>(PhantomData<T>);
#[solidity_interface(name = GenericIs)]
impl<T> Generic<T> {
crates/evm-coder/tests/random.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/random.rs
+++ b/crates/evm-coder/tests/random.rs
@@ -18,7 +18,7 @@
use evm_coder::{ToLog, execution::Result, solidity_interface, types::*, solidity, weight};
-struct Impls;
+pub struct Impls;
#[solidity_interface(name = OurInterface)]
impl Impls {
crates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/solidity_generation.rs
+++ b/crates/evm-coder/tests/solidity_generation.rs
@@ -16,7 +16,7 @@
use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};
-struct ERC20;
+pub struct ERC20;
#[solidity_interface(name = ERC20)]
impl ERC20 {
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -406,9 +406,9 @@
true => {
let mut bv = OwnerRestrictedSet::new();
for i in collections {
- bv.try_insert(crate::eth::map_eth_to_id(&i).ok_or(Error::Revert(
- "Can't convert address into collection id".into(),
- ))?)
+ bv.try_insert(crate::eth::map_eth_to_id(&i).ok_or_else(|| {
+ Error::Revert("Can't convert address into collection id".into())
+ })?)
.map_err(|_| "too many collections")?;
}
let mut nesting = permissions.nesting().clone();
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -199,7 +199,7 @@
ERC20,
ERC20Mintable,
ERC20UniqueExtensions,
- Collection(common_mut, CollectionHandle<T>),
+ Collection(via(common_mut returns CollectionHandle<T>)),
)
)]
impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -736,7 +736,7 @@
ERC721UniqueExtensions,
ERC721Mintable,
ERC721Burnable,
- Collection(common_mut, CollectionHandle<T>),
+ Collection(via(common_mut returns CollectionHandle<T>)),
TokenProperties,
)
)]
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -785,7 +785,7 @@
ERC721UniqueExtensions,
ERC721Mintable,
ERC721Burnable,
- Collection(common_mut, CollectionHandle<T>),
+ Collection(via(common_mut returns CollectionHandle<T>)),
TokenProperties,
)
)]