git.delta.rocks / unique-network / refs/commits / dc753ac3eb78

difftreelog

feat solidity code generation

Yaroslav Bolyukin2021-07-22parent: #ab49fc9.patch.diff
in: master

2 files changed

modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
--- a/crates/evm-coder-macros/src/solidity_interface.rs
+++ b/crates/evm-coder-macros/src/solidity_interface.rs
@@ -4,7 +4,10 @@
 use darling::FromMeta;
 use inflector::cases;
 use std::fmt::Write;
-use syn::{FnArg, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Meta, NestedMeta, PatType, Path, ReturnType, Type, spanned::Spanned};
+use syn::{
+	FnArg, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Meta, NestedMeta, PatType, Path,
+	ReturnType, Type, spanned::Spanned,
+};
 
 use crate::{
 	fn_selector_str, parse_ident_from_pat, parse_ident_from_path, parse_ident_from_type,
@@ -163,6 +166,14 @@
 			}
 		}
 	}
+
+	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
+		let name = &self.name.to_string();
+		let ty = &self.ty;
+		quote! {
+			<NamedArgument<#ty>>::new(#name)
+		}
+	}
 }
 
 #[derive(PartialEq)]
@@ -376,10 +387,35 @@
 			}
 		}
 	}
+
+	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
+		let camel_name = &self.camel_name;
+		let mutability = match self.mutability {
+			Mutability::Mutable => quote! {SolidityMutability::Mutable},
+			Mutability::View => quote! { SolidityMutability::View },
+			Mutability::Pure => quote! {SolidityMutability::Pure},
+		};
+		let result = &self.result;
+
+		let args = self.args.iter().map(MethodArg::expand_solidity_argument);
+
+		quote! {
+			SolidityFunction {
+				name: #camel_name,
+				mutability: #mutability,
+				args: (
+					#(
+						#args,
+					)*
+				),
+				result: <UnnamedArgument<#result>>::default(),
+			}
+		}
+	}
 }
 
 pub struct SolidityInterface {
-    generics: Generics,
+	generics: Generics,
 	name: Box<syn::Type>,
 	info: InterfaceInfo,
 	methods: Vec<Method>,
@@ -394,7 +430,7 @@
 			}
 		}
 		Ok(Self {
-            generics: value.generics.clone(),
+			generics: value.generics.clone(),
 			name: value.self_ty.clone(),
 			info,
 			methods,
@@ -403,8 +439,9 @@
 	pub fn expand(self) -> proc_macro2::TokenStream {
 		let name = self.name;
 
+		let solidity_name = self.info.name.to_string();
 		let call_name = pascal_ident_to_call(&self.info.name);
-        let generics = self.generics;
+		let generics = self.generics;
 
 		let call_sub = self
 			.info
@@ -436,6 +473,7 @@
 		let interface_id = self.methods.iter().map(Method::expand_interface_id);
 		let parsers = self.methods.iter().map(Method::expand_parse);
 		let call_variants_this = self.methods.iter().map(Method::expand_variant_call);
+		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);
 
 		// let methods = self.methods.iter().map(Method::solidity_def);
 
@@ -467,6 +505,19 @@
 						)*
 					)
 				}
+				pub fn generate_solidity_interface() -> string {
+					use evm_coder::solidity::*;
+					use core::fmt::Write;
+					let interface = SolidityInterface {
+						name: #solidity_name,
+						functions: (#(
+							#solidity_functions,
+						)*),
+					};
+					let mut out = string::new();
+					let _ = interface.format(&mut out);
+					out
+				}
 			}
 			impl ::evm_coder::Call for #call_name {
 				fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
1#[cfg(not(feature = "std"))]
2use alloc::{string::String};
1use core::{fmt, marker::PhantomData};3use core::{fmt, marker::PhantomData};
2use impl_trait_for_tuples::impl_for_tuples;4use impl_trait_for_tuples::impl_for_tuples;
3use crate::types::*;5use crate::types::*;
2325
24solidity_type_name! {26solidity_type_name! {
25 uint8 => "uint8",27 uint8 => "uint8",
28 uint32 => "uint32",
29 uint128 => "uint128",
30 uint256 => "uint256",
26 address => "address",31 address => "address",
27 string => "memory string",32 string => "memory string",
33 bytes => "memory bytes",
34 bool => "bool",
28}35}
29impl SolidityTypeName for void {36impl SolidityTypeName for void {
30 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {37 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {
43 fn len(&self) -> usize;50 fn len(&self) -> usize;
44}51}
4552
53#[derive(Default)]
46pub struct UnnamedArgument<T>(PhantomData<*const T>);54pub struct UnnamedArgument<T>(PhantomData<*const T>);
4755
48impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {56impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {
6472
65pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);73pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);
74
75impl<T> NamedArgument<T> {
76 pub fn new(name: &'static str) -> Self {
77 Self(name, Default::default())
78 }
79}
6680
67impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {81impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {
68 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {82 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
96 for_tuples!( where #( Tuple: SolidityArguments ),* );110 for_tuples!( where #( Tuple: SolidityArguments ),* );
97111
98 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {112 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
99 let mut first = false;113 let mut first = true;
100 for_tuples!( #(114 for_tuples!( #(
101 if !Tuple.is_empty() {115 if !Tuple.is_empty() {
102 if first {116 if !first {
103 write!(writer, ", ")?;117 write!(writer, ", ")?;
104 }118 }
105 first = false;119 first = false;
113 }127 }
114}128}
115129
116trait SolidityFunctions {130pub trait SolidityFunctions {
117 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;131 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;
118}132}
119133
123 Mutable,137 Mutable,
124}138}
125pub struct SolidityFunction<A, R> {139pub struct SolidityFunction<A, R> {
126 name: &'static str,140 pub name: &'static str,
127 args: A,141 pub args: A,
128 result: R,142 pub result: R,
129 mutability: SolidityMutability,143 pub mutability: SolidityMutability,
130}144}
131impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {145impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {
132 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {146 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {
133 write!(writer, "function {}(", self.name)?;147 write!(writer, "function {}(", self.name)?;
134 self.args.solidity_name(writer)?;148 self.args.solidity_name(writer)?;
135 write!(writer, ") public")?;149 write!(writer, ") external")?;
136 match &self.mutability {150 match &self.mutability {
137 SolidityMutability::Pure => write!(writer, " pure")?,151 SolidityMutability::Pure => write!(writer, " pure")?,
138 SolidityMutability::View => write!(writer, " view")?,152 SolidityMutability::View => write!(writer, " view")?,
139 SolidityMutability::Mutable => {}153 SolidityMutability::Mutable => {}
140 }154 }
141 if !self.result.is_empty() {155 if !self.result.is_empty() {
142 write!(writer, "returns (")?;156 write!(writer, " returns (")?;
143 self.result.solidity_name(writer)?;157 self.result.solidity_name(writer)?;
144 write!(writer, ")")?;158 write!(writer, ")")?;
145 }159 }
160 }174 }
161}175}
162176
177pub struct SolidityInterface<F: SolidityFunctions> {
178 pub name: &'static str,
179 pub functions: F,
180}
181
182impl<F: SolidityFunctions> SolidityInterface<F> {
183 pub fn format(&self, out: &mut impl fmt::Write) -> fmt::Result {
184 writeln!(out, "interface {} {{", self.name)?;
185 self.functions.solidity_name(out)?;
186 writeln!(out, "}}")?;
187 Ok(())
188 }
189}