git.delta.rocks / unique-network / refs/commits / 488175cd133a

difftreelog

Merge pull request #569 from UniqueNetwork/feature/evm-conditional-inheritance

Yaroslav Bolyukin2022-09-19parents: #065efcf #3fefb83.patch.diff
in: master

11 files changed

modifiedcrates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth
42 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 }
7177
93 .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();
152
153 let mut condition: Option<Expr> = None;
141 let via = if lookahead.peek(syn::token::Paren) {154 let mut via: Option<(Type, Ident)> = None;
155
156 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;
160
161 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>()?;
168
169 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);
176
144 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>()?;
180
147 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 }
187
188 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 // Pass
150 } else if input.is_empty() {
151 None
152 } 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);
496541
497 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 selector
1000 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_interface
1006 )*
1007 )
1008 }
1009 /// Generate solidity definitions for methods described in this interface1045 /// Generate solidity definitions for methods described in this interface
1010 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 };
10261062
1027 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_ref
1102 #gen_where
1103 {
1104 /// Is this contract implements specified ERC165 selector
1105 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_interface
1111 )*
1112 )
1113 }
1114 }
1115 impl #generics ::evm_coder::Weighted for #call_name #gen_ref
1066 #gen_where1116 #gen_where
1067 {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 }
modifiedcrates/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()
modifiedcrates/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> {
addedcrates/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
+	));
+}
modifiedcrates/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> {
modifiedcrates/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 {
modifiedcrates/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 {
modifiedpallets/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();
modifiedpallets/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]> {}
modifiedpallets/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,
 	)
 )]
modifiedpallets/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,
 	)
 )]