git.delta.rocks / unique-network / refs/commits / 8057bddf39cb

difftreelog

source

crates/evm-coder/src/solidity.rs8.0 KiBsourcehistory
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 solidity_default(writer: &mut impl fmt::Write) -> fmt::Result;10	fn is_void() -> bool {11		false12	}13}1415macro_rules! solidity_type_name {16    ($($ty:ident => $name:literal = $default:literal),* $(,)?) => {17        $(18            impl SolidityTypeName for $ty {19                fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {20                    write!(writer, $name)21                }22				fn solidity_default(writer: &mut impl core::fmt::Write) -> core::fmt::Result {23					write!(writer, $default)24				}25            }26        )*27    };28}2930solidity_type_name! {31	uint8 => "uint8" = "0",32	uint32 => "uint32" = "0",33	uint128 => "uint128" = "0",34	uint256 => "uint256" = "0",35	address => "address" = "0x0000000000000000000000000000000000000000",36	string => "string memory" = "\"\"",37	bytes => "bytes memory" = "hex\"\"",38	bool => "bool" = "false",39}40impl SolidityTypeName for void {41	fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {42		Ok(())43	}44	fn solidity_default(_writer: &mut impl fmt::Write) -> fmt::Result {45		Ok(())46	}47	fn is_void() -> bool {48		true49	}50}5152pub trait SolidityArguments {53	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;54	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result;55	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result;56	fn is_empty(&self) -> bool {57		self.len() == 058	}59	fn len(&self) -> usize;60}6162#[derive(Default)]63pub struct UnnamedArgument<T>(PhantomData<*const T>);6465impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {66	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {67		if !T::is_void() {68			T::solidity_name(writer)69		} else {70			Ok(())71		}72	}73	fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {74		Ok(())75	}76	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {77		T::solidity_default(writer)78	}79	fn len(&self) -> usize {80		if T::is_void() {81			082		} else {83			184		}85	}86}8788pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);8990impl<T> NamedArgument<T> {91	pub fn new(name: &'static str) -> Self {92		Self(name, Default::default())93	}94}9596impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {97	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {98		if !T::is_void() {99			T::solidity_name(writer)?;100			write!(writer, " {}", self.0)101		} else {102			Ok(())103		}104	}105	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {106		writeln!(writer, "\t\t{};", self.0)107	}108	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {109		T::solidity_default(writer)110	}111	fn len(&self) -> usize {112		if T::is_void() {113			0114		} else {115			1116		}117	}118}119120pub struct SolidityEventArgument<T>(pub bool, &'static str, PhantomData<*const T>);121122impl<T> SolidityEventArgument<T> {123	pub fn new(indexed: bool, name: &'static str) -> Self {124		Self(indexed, name, Default::default())125	}126}127128impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {129	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {130		if !T::is_void() {131			T::solidity_name(writer)?;132			if self.0 {133				write!(writer, " indexed")?;134			}135			write!(writer, " {}", self.1)136		} else {137			Ok(())138		}139	}140	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {141		writeln!(writer, "\t\t{};", self.1)142	}143	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {144		T::solidity_default(writer)145	}146	fn len(&self) -> usize {147		if T::is_void() {148			0149		} else {150			1151		}152	}153}154155impl SolidityArguments for () {156	fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {157		Ok(())158	}159	fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {160		Ok(())161	}162	fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result {163		Ok(())164	}165	fn len(&self) -> usize {166		0167	}168}169170#[impl_for_tuples(1, 5)]171impl SolidityArguments for Tuple {172	for_tuples!( where #( Tuple: SolidityArguments ),* );173174	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {175		let mut first = true;176		for_tuples!( #(177            if !Tuple.is_empty() {178                if !first {179                    write!(writer, ", ")?;180                }181                first = false;182                Tuple.solidity_name(writer)?;183            }184        )* );185		Ok(())186	}187	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {188		for_tuples!( #(189            Tuple.solidity_get(writer)?;190        )* );191		Ok(())192	}193	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {194		if self.is_empty() {195			Ok(())196		} else if self.len() == 1 {197			for_tuples!( #(198				Tuple.solidity_default(writer)?;199			)* );200			Ok(())201		} else {202			write!(writer, "(")?;203			let mut first = true;204			for_tuples!( #(205				if !Tuple.is_empty() {206					if !first {207						write!(writer, ", ")?;208					}209					first = false;210					Tuple.solidity_name(writer)?;211				}212			)* );213			write!(writer, ")")?;214			Ok(())215		}216	}217	fn len(&self) -> usize {218		for_tuples!( #( Tuple.len() )+* )219	}220}221222pub trait SolidityFunctions {223	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result;224}225226pub enum SolidityMutability {227	Pure,228	View,229	Mutable,230}231pub struct SolidityFunction<A, R> {232	pub name: &'static str,233	pub args: A,234	pub result: R,235	pub mutability: SolidityMutability,236}237impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {238	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {239		write!(writer, "\tfunction {}(", self.name)?;240		self.args.solidity_name(writer)?;241		write!(writer, ")")?;242		if is_impl {243			write!(writer, " public")?;244		} else {245			write!(writer, " external")?;246		}247		match &self.mutability {248			SolidityMutability::Pure => write!(writer, " pure")?,249			SolidityMutability::View => write!(writer, " view")?,250			SolidityMutability::Mutable => {}251		}252		if !self.result.is_empty() {253			write!(writer, " returns (")?;254			self.result.solidity_name(writer)?;255			write!(writer, ")")?;256		}257		if is_impl {258			writeln!(writer, " {{")?;259			writeln!(writer, "\t\trequire(false, stub_error);")?;260			self.args.solidity_get(writer)?;261			match &self.mutability {262				SolidityMutability::Pure => {}263				SolidityMutability::View => writeln!(writer, "\t\tdummy;")?,264				SolidityMutability::Mutable => writeln!(writer, "\t\tdummy = 0;")?,265			}266			if !self.result.is_empty() {267				write!(writer, "\t\treturn ")?;268				self.result.solidity_default(writer)?;269				writeln!(writer, ";")?;270			}271			writeln!(writer, "\t}}")?;272		} else {273			writeln!(writer, ";")?;274		}275		Ok(())276	}277}278279#[impl_for_tuples(0, 12)]280impl SolidityFunctions for Tuple {281	for_tuples!( where #( Tuple: SolidityFunctions ),* );282283	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {284		let mut first = false;285		for_tuples!( #(286            Tuple.solidity_name(is_impl, writer)?;287        )* );288		Ok(())289	}290}291292pub struct SolidityInterface<F: SolidityFunctions> {293	pub name: &'static str,294	pub is: &'static [&'static str],295	pub functions: F,296}297298impl<F: SolidityFunctions> SolidityInterface<F> {299	pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result {300		if is_impl {301			write!(out, "contract ")?;302		} else {303			write!(out, "interface ")?;304		}305		write!(out, "{}", self.name)?;306		if !self.is.is_empty() {307			write!(out, " is")?;308			for (i, n) in self.is.iter().enumerate() {309				if i != 0 {310					write!(out, ",")?;311				}312				write!(out, " {}", n)?;313			}314		}315		writeln!(out, " {{")?;316		self.functions.solidity_name(is_impl, out)?;317		writeln!(out, "}}")?;318		Ok(())319	}320}321322pub struct SolidityEvent<A> {323	pub name: &'static str,324	pub args: A,325}326327impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {328	fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {329		write!(writer, "\tevent {}(", self.name)?;330		self.args.solidity_name(writer)?;331		writeln!(writer, ");")332	}333}