difftreelog
feat solidity code generation
in: master
2 files changed
crates/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>> {
crates/evm-coder/src/solidity.rsdiffbeforeafterboth1use core::{fmt, marker::PhantomData};2use impl_trait_for_tuples::impl_for_tuples;3use crate::types::*;45pub trait SolidityTypeName: 'static {6 fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;7 fn is_void() -> bool {8 false9 }10}1112macro_rules! solidity_type_name {13 ($($ty:ident => $name:expr),* $(,)?) => {14 $(15 impl SolidityTypeName for $ty {16 fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {17 write!(writer, $name)18 }19 }20 )*21 };22}2324solidity_type_name! {25 uint8 => "uint8",26 address => "address",27 string => "memory string",28}29impl SolidityTypeName for void {30 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {31 Ok(())32 }33 fn is_void() -> bool {34 true35 }36}3738pub trait SolidityArguments {39 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;40 fn is_empty(&self) -> bool {41 self.len() == 042 }43 fn len(&self) -> usize;44}4546pub struct UnnamedArgument<T>(PhantomData<*const T>);4748impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {49 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {50 if !T::is_void() {51 T::solidity_name(writer)52 } else {53 Ok(())54 }55 }56 fn len(&self) -> usize {57 if T::is_void() {58 059 } else {60 161 }62 }63}6465pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);6667impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {68 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {69 if !T::is_void() {70 T::solidity_name(writer)?;71 write!(writer, " {}", self.0)72 } else {73 Ok(())74 }75 }76 fn len(&self) -> usize {77 if T::is_void() {78 079 } else {80 181 }82 }83}8485impl SolidityArguments for () {86 fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {87 Ok(())88 }89 fn len(&self) -> usize {90 091 }92}9394#[impl_for_tuples(1, 5)]95impl SolidityArguments for Tuple {96 for_tuples!( where #( Tuple: SolidityArguments ),* );9798 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {99 let mut first = false;100 for_tuples!( #(101 if !Tuple.is_empty() {102 if first {103 write!(writer, ", ")?;104 }105 first = false;106 Tuple.solidity_name(writer)?;107 }108 )* );109 Ok(())110 }111 fn len(&self) -> usize {112 for_tuples!( #( Tuple.len() )+* )113 }114}115116trait SolidityFunctions {117 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;118}119120pub enum SolidityMutability {121 Pure,122 View,123 Mutable,124}125pub struct SolidityFunction<A, R> {126 name: &'static str,127 args: A,128 result: R,129 mutability: SolidityMutability,130}131impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {132 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {133 write!(writer, "function {}(", self.name)?;134 self.args.solidity_name(writer)?;135 write!(writer, ") public")?;136 match &self.mutability {137 SolidityMutability::Pure => write!(writer, " pure")?,138 SolidityMutability::View => write!(writer, " view")?,139 SolidityMutability::Mutable => {}140 }141 if !self.result.is_empty() {142 write!(writer, "returns (")?;143 self.result.solidity_name(writer)?;144 write!(writer, ")")?;145 }146 writeln!(writer, ";")147 }148}149150#[impl_for_tuples(0, 12)]151impl SolidityFunctions for Tuple {152 for_tuples!( where #( Tuple: SolidityFunctions ),* );153154 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {155 let mut first = false;156 for_tuples!( #(157 Tuple.solidity_name(writer)?;158 )* );159 Ok(())160 }161}1#[cfg(not(feature = "std"))]2use alloc::{string::String};3use core::{fmt, marker::PhantomData};4use impl_trait_for_tuples::impl_for_tuples;5use crate::types::*;67pub trait SolidityTypeName: 'static {8 fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;9 fn is_void() -> bool {10 false11 }12}1314macro_rules! solidity_type_name {15 ($($ty:ident => $name:expr),* $(,)?) => {16 $(17 impl SolidityTypeName for $ty {18 fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {19 write!(writer, $name)20 }21 }22 )*23 };24}2526solidity_type_name! {27 uint8 => "uint8",28 uint32 => "uint32",29 uint128 => "uint128",30 uint256 => "uint256",31 address => "address",32 string => "memory string",33 bytes => "memory bytes",34 bool => "bool",35}36impl SolidityTypeName for void {37 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {38 Ok(())39 }40 fn is_void() -> bool {41 true42 }43}4445pub trait SolidityArguments {46 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;47 fn is_empty(&self) -> bool {48 self.len() == 049 }50 fn len(&self) -> usize;51}5253#[derive(Default)]54pub struct UnnamedArgument<T>(PhantomData<*const T>);5556impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {57 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {58 if !T::is_void() {59 T::solidity_name(writer)60 } else {61 Ok(())62 }63 }64 fn len(&self) -> usize {65 if T::is_void() {66 067 } else {68 169 }70 }71}7273pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);7475impl<T> NamedArgument<T> {76 pub fn new(name: &'static str) -> Self {77 Self(name, Default::default())78 }79}8081impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {82 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {83 if !T::is_void() {84 T::solidity_name(writer)?;85 write!(writer, " {}", self.0)86 } else {87 Ok(())88 }89 }90 fn len(&self) -> usize {91 if T::is_void() {92 093 } else {94 195 }96 }97}9899impl SolidityArguments for () {100 fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {101 Ok(())102 }103 fn len(&self) -> usize {104 0105 }106}107108#[impl_for_tuples(1, 5)]109impl SolidityArguments for Tuple {110 for_tuples!( where #( Tuple: SolidityArguments ),* );111112 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {113 let mut first = true;114 for_tuples!( #(115 if !Tuple.is_empty() {116 if !first {117 write!(writer, ", ")?;118 }119 first = false;120 Tuple.solidity_name(writer)?;121 }122 )* );123 Ok(())124 }125 fn len(&self) -> usize {126 for_tuples!( #( Tuple.len() )+* )127 }128}129130pub trait SolidityFunctions {131 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;132}133134pub enum SolidityMutability {135 Pure,136 View,137 Mutable,138}139pub struct SolidityFunction<A, R> {140 pub name: &'static str,141 pub args: A,142 pub result: R,143 pub mutability: SolidityMutability,144}145impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {146 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {147 write!(writer, "function {}(", self.name)?;148 self.args.solidity_name(writer)?;149 write!(writer, ") external")?;150 match &self.mutability {151 SolidityMutability::Pure => write!(writer, " pure")?,152 SolidityMutability::View => write!(writer, " view")?,153 SolidityMutability::Mutable => {}154 }155 if !self.result.is_empty() {156 write!(writer, " returns (")?;157 self.result.solidity_name(writer)?;158 write!(writer, ")")?;159 }160 writeln!(writer, ";")161 }162}163164#[impl_for_tuples(0, 12)]165impl SolidityFunctions for Tuple {166 for_tuples!( where #( Tuple: SolidityFunctions ),* );167168 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {169 let mut first = false;170 for_tuples!( #(171 Tuple.solidity_name(writer)?;172 )* );173 Ok(())174 }175}176177pub struct SolidityInterface<F: SolidityFunctions> {178 pub name: &'static str,179 pub functions: F,180}181182impl<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}