git.delta.rocks / unique-network / refs/commits / 8e4698bc6eb3

difftreelog

source

crates/evm-coder/src/solidity.rs7.2 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}119120impl SolidityArguments for () {121	fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {122		Ok(())123	}124	fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {125		Ok(())126	}127	fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result {128		Ok(())129	}130	fn len(&self) -> usize {131		0132	}133}134135#[impl_for_tuples(1, 5)]136impl SolidityArguments for Tuple {137	for_tuples!( where #( Tuple: SolidityArguments ),* );138139	fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {140		let mut first = true;141		for_tuples!( #(142            if !Tuple.is_empty() {143                if !first {144                    write!(writer, ", ")?;145                }146                first = false;147                Tuple.solidity_name(writer)?;148            }149        )* );150		Ok(())151	}152	fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {153		for_tuples!( #(154            Tuple.solidity_get(writer)?;155        )* );156		Ok(())157	}158	fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {159		if self.is_empty() {160			Ok(())161		} else if self.len() == 1 {162			for_tuples!( #(163				Tuple.solidity_default(writer)?;164			)* );165			Ok(())166		} else {167			write!(writer, "(")?;168			let mut first = true;169			for_tuples!( #(170				if !Tuple.is_empty() {171					if !first {172						write!(writer, ", ")?;173					}174					first = false;175					Tuple.solidity_name(writer)?;176				}177			)* );178			write!(writer, ")")?;179			Ok(())180		}181	}182	fn len(&self) -> usize {183		for_tuples!( #( Tuple.len() )+* )184	}185}186187pub trait SolidityFunctions {188	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result;189}190191pub enum SolidityMutability {192	Pure,193	View,194	Mutable,195}196pub struct SolidityFunction<A, R> {197	pub name: &'static str,198	pub args: A,199	pub result: R,200	pub mutability: SolidityMutability,201}202impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {203	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {204		write!(writer, "\tfunction {}(", self.name)?;205		self.args.solidity_name(writer)?;206		write!(writer, ")")?;207		if is_impl {208			write!(writer, " public")?;209		} else {210			write!(writer, " external")?;211		}212		match &self.mutability {213			SolidityMutability::Pure => write!(writer, " pure")?,214			SolidityMutability::View => write!(writer, " view")?,215			SolidityMutability::Mutable => {}216		}217		if !self.result.is_empty() {218			write!(writer, " returns (")?;219			self.result.solidity_name(writer)?;220			write!(writer, ")")?;221		}222		if is_impl {223			writeln!(writer, " {{")?;224			writeln!(writer, "\t\trequire(false, stub_error);")?;225			self.args.solidity_get(writer)?;226			match &self.mutability {227				SolidityMutability::Pure => {}228				SolidityMutability::View => writeln!(writer, "\t\tdummy;")?,229				SolidityMutability::Mutable => writeln!(writer, "\t\tdummy = 0;")?,230			}231			if !self.result.is_empty() {232				write!(writer, "\t\treturn ")?;233				self.result.solidity_default(writer)?;234				writeln!(writer, ";")?;235			}236			writeln!(writer, "\t}}")?;237		} else {238			writeln!(writer, ";")?;239		}240		Ok(())241	}242}243244#[impl_for_tuples(0, 12)]245impl SolidityFunctions for Tuple {246	for_tuples!( where #( Tuple: SolidityFunctions ),* );247248	fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {249		let mut first = false;250		for_tuples!( #(251            Tuple.solidity_name(is_impl, writer)?;252        )* );253		Ok(())254	}255}256257pub struct SolidityInterface<F: SolidityFunctions> {258	pub name: &'static str,259	pub is: &'static [&'static str],260	pub functions: F,261}262263impl<F: SolidityFunctions> SolidityInterface<F> {264	pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result {265		if is_impl {266			write!(out, "contract ")?;267		} else {268			write!(out, "interface ")?;269		}270		write!(out, "{}", self.name)?;271		if !self.is.is_empty() {272			write!(out, " is")?;273			for (i, n) in self.is.iter().enumerate() {274				if i != 0 {275					write!(out, ",")?;276				}277				write!(out, " {}", n)?;278			}279		}280		writeln!(out, " {{")?;281		self.functions.solidity_name(is_impl, out)?;282		writeln!(out, "}}")?;283		Ok(())284	}285}286287pub struct SolidityEvent<A> {288	pub name: &'static str,289	pub args: A,290}291292impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {293	fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {294		write!(writer, "\tevent {}(", self.name)?;295		self.args.solidity_name(writer)?;296		writeln!(writer, ");")297	}298}