git.delta.rocks / unique-network / refs/commits / 12eee8195c76

difftreelog

misk: Generate solidity docs for struct

Trubnikov Sergey2022-11-21parent: #3e03fdf.patch.diff
in: master

4 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive.rs
+++ b/crates/evm-coder/procedural/src/abi_derive.rs
@@ -2,6 +2,29 @@
 
 pub(crate) fn impl_abi_macro(ast: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
 	let name = &ast.ident;
+	let docs = ast
+		.attrs
+		.iter()
+		.filter_map(|attr| {
+			if let Some(ps) = attr.path.segments.first() {
+				if ps.ident == "doc" {
+					let meta = match attr.parse_meta() {
+						Ok(meta) => meta,
+						Err(e) => return Some(Err(e)),
+					};
+					match meta {
+						syn::Meta::NameValue(mnv) => match &mnv.lit {
+							syn::Lit::Str(ls) => return Some(Ok(ls.value())),
+							_ => unreachable!(),
+						},
+						_ => unreachable!(),
+					}
+				}
+			}
+			None
+		})
+		.collect::<syn::Result<Vec<_>>>()?;
+
 	let (is_named_fields, field_names, field_types, params_count) = match &ast.data {
 		syn::Data::Struct(ds) => match ds.fields {
 			syn::Fields::Named(ref fields) => Ok((
@@ -37,7 +60,8 @@
 	let abi_write = impl_abi_write(name, is_named_fields, params_count, field_names.clone());
 	let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);
 	let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count);
-	let solidity_struct_collect = impl_solidity_struct_collect(name, field_names, field_types);
+	let solidity_struct_collect =
+		impl_solidity_struct_collect(name, field_names, field_types, &docs);
 
 	Ok(quote! {
 		#can_be_plcaed_in_vec
@@ -259,6 +283,7 @@
 	name: &syn::Ident,
 	field_names: impl Iterator<Item = proc_macro2::Ident> + Clone,
 	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
+	docs: &Vec<String>,
 ) -> proc_macro2::TokenStream {
 	let string_name = name.to_string();
 	let name_type = field_names
@@ -271,6 +296,13 @@
 				write!(str, "{};", #name).unwrap();
 			)
 		});
+	let docs = docs.iter().enumerate().map(|(i, doc)| {
+		let doc = doc.trim();
+		let dev = if i == 0 { " @dev" } else { "" };
+		quote! {
+			writeln!(str, "///{} {}", #dev, #doc).unwrap();
+		}
+	});
 
 	quote! {
 		#[cfg(feature = "stubgen")]
@@ -283,7 +315,7 @@
 				use std::fmt::Write;
 
 				let mut str = String::new();
-				writeln!(str, "/// @dev Cross account struct").unwrap();
+				#(#docs)*
 				writeln!(str, "struct {} {{", Self::name()).unwrap();
 				#(#name_type)*
 				writeln!(str, "}}").unwrap();
modifiedcrates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/impls.rs
+++ b/crates/evm-coder/src/solidity/impls.rs
@@ -1,6 +1,7 @@
 use super::{TypeCollector, SolidityTypeName, SolidityType, StructCollect};
 use crate::{sealed, types::*};
 use core::fmt;
+use primitive_types::{U256, H160};
 
 macro_rules! solidity_type_name {
     ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => {
@@ -31,13 +32,13 @@
 }
 
 solidity_type_name! {
-	uint8 => "uint8" true = "0",
-	uint32 => "uint32" true = "0",
-	uint64 => "uint64" true = "0",
-	uint128 => "uint128" true = "0",
-	uint256 => "uint256" true = "0",
+	u8 => "uint8" true = "0",
+	u32 => "uint32" true = "0",
+	u64 => "uint64" true = "0",
+	u128 => "uint128" true = "0",
+	U256 => "uint256" true = "0",
 	bytes4 => "bytes4" true = "bytes4(0)",
-	address => "address" true = "0x0000000000000000000000000000000000000000",
+	H160 => "address" true = "0x0000000000000000000000000000000000000000",
 	string => "string" false = "\"\"",
 	bytes => "bytes" false = "hex\"\"",
 	bool => "bool" true = "false",
modifiedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ b/crates/evm-coder/tests/abi_derive_generation.rs
@@ -57,10 +57,16 @@
 	_b: TypeStruct2DynamicParam,
 }
 
+/// Some docs
+/// At multi
+/// line
 #[derive(AbiCoder, PartialEq, Debug)]
 struct TypeStruct3DerivedMixedParam {
+	/// Docs for A
 	_a: TypeStruct1SimpleParam,
+	/// Docs for B
 	_b: TypeStruct2DynamicParam,
+	/// Docs for C
 	_c: TypeStruct2MixedParam,
 }
 
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
before · pallets/common/src/eth.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.1819use evm_coder::{20	AbiCoder,21	types::{uint256, address},22};23pub use pallet_evm::{Config, account::CrossAccountId};24use sp_core::H160;25use up_data_structs::CollectionId;2627// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 128// TODO: Unhardcode prefix29const ETH_COLLECTION_PREFIX: [u8; 16] = [30	0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,31];3233/// Maps the ethereum address of the collection in substrate.34pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {35	if eth[0..16] != ETH_COLLECTION_PREFIX {36		return None;37	}38	let mut id_bytes = [0; 4];39	id_bytes.copy_from_slice(&eth[16..20]);40	Some(CollectionId(u32::from_be_bytes(id_bytes)))41}4243/// Maps the substrate collection id in ethereum.44pub fn collection_id_to_address(id: CollectionId) -> H160 {45	let mut out = [0; 20];46	out[0..16].copy_from_slice(&ETH_COLLECTION_PREFIX);47	out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));48	H160(out)49}5051/// Check if the ethereum address is a collection.52pub fn is_collection(address: &H160) -> bool {53	address[0..16] == ETH_COLLECTION_PREFIX54}5556/// Convert `CrossAccountId` to `uint256`.57pub fn convert_cross_account_to_uint256<T: Config>(from: &T::CrossAccountId) -> uint25658where59	T::AccountId: AsRef<[u8; 32]>,60{61	let slice = from.as_sub().as_ref();62	uint256::from_big_endian(slice)63}6465/// Convert `uint256` to `CrossAccountId`.66pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId67where68	T::AccountId: From<[u8; 32]>,69{70	let mut new_admin_arr = [0_u8; 32];71	from.to_big_endian(&mut new_admin_arr);72	let account_id = T::AccountId::from(new_admin_arr);73	T::CrossAccountId::from_sub(account_id)74}7576/// Convert `CrossAccountId` to `(address, uint256)`.77pub fn convert_cross_account_to_tuple<T: Config>(78	cross_account_id: &T::CrossAccountId,79) -> (address, uint256)80where81	T::AccountId: AsRef<[u8; 32]>,82{83	if cross_account_id.is_canonical_substrate() {84		let sub = convert_cross_account_to_uint256::<T>(cross_account_id);85		(Default::default(), sub)86	} else {87		let eth = *cross_account_id.as_eth();88		(eth, Default::default())89	}90}9192/// Convert tuple `(address, uint256)` to `CrossAccountId`.93///94/// If `address` in the tuple has *default* value, then the canonical form is substrate,95/// if `uint256` has *default* value, then the ethereum form is canonical,96/// if both values are *default* or *non default*, then this is considered an invalid address and `Error` is returned.97pub fn convert_tuple_to_cross_account<T: Config>(98	eth_cross_account_id: (address, uint256),99) -> evm_coder::execution::Result<T::CrossAccountId>100where101	T::AccountId: From<[u8; 32]>,102{103	if eth_cross_account_id == Default::default() {104		Err("All fields of cross account is zeroed".into())105	} else if eth_cross_account_id.0 == Default::default() {106		Ok(convert_uint256_to_cross_account::<T>(107			eth_cross_account_id.1,108		))109	} else if eth_cross_account_id.1 == Default::default() {110		Ok(T::CrossAccountId::from_eth(eth_cross_account_id.0))111	} else {112		Err("All fields of cross account is non zeroed".into())113	}114}115116#[derive(Debug, Default, AbiCoder)]117pub struct EthCrossAccount {118	pub(crate) eth: address,119	pub(crate) sub: uint256,120}121122impl EthCrossAccount {123	pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self124	where125		T: pallet_evm::account::Config,126		T::AccountId: AsRef<[u8; 32]>,127	{128		if cross_account_id.is_canonical_substrate() {129			Self {130				eth: Default::default(),131				sub: convert_cross_account_to_uint256::<T>(cross_account_id),132			}133		} else {134			Self {135				eth: *cross_account_id.as_eth(),136				sub: Default::default(),137			}138		}139	}140141	pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>142	where143		T: pallet_evm::account::Config,144		T::AccountId: From<[u8; 32]>,145	{146		if self.eth == Default::default() && self.sub == Default::default() {147			Err("All fields of cross account is zeroed".into())148		} else if self.eth == Default::default() {149			Ok(convert_uint256_to_cross_account::<T>(self.sub))150		} else if self.sub == Default::default() {151			Ok(T::CrossAccountId::from_eth(self.eth))152		} else {153			Err("All fields of cross account is non zeroed".into())154		}155	}156}
after · pallets/common/src/eth.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.1819use evm_coder::{20	AbiCoder,21	types::{uint256, address},22};23pub use pallet_evm::{Config, account::CrossAccountId};24use sp_core::H160;25use up_data_structs::CollectionId;2627// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 128// TODO: Unhardcode prefix29const ETH_COLLECTION_PREFIX: [u8; 16] = [30	0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,31];3233/// Maps the ethereum address of the collection in substrate.34pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {35	if eth[0..16] != ETH_COLLECTION_PREFIX {36		return None;37	}38	let mut id_bytes = [0; 4];39	id_bytes.copy_from_slice(&eth[16..20]);40	Some(CollectionId(u32::from_be_bytes(id_bytes)))41}4243/// Maps the substrate collection id in ethereum.44pub fn collection_id_to_address(id: CollectionId) -> H160 {45	let mut out = [0; 20];46	out[0..16].copy_from_slice(&ETH_COLLECTION_PREFIX);47	out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));48	H160(out)49}5051/// Check if the ethereum address is a collection.52pub fn is_collection(address: &H160) -> bool {53	address[0..16] == ETH_COLLECTION_PREFIX54}5556/// Convert `CrossAccountId` to `uint256`.57pub fn convert_cross_account_to_uint256<T: Config>(from: &T::CrossAccountId) -> uint25658where59	T::AccountId: AsRef<[u8; 32]>,60{61	let slice = from.as_sub().as_ref();62	uint256::from_big_endian(slice)63}6465/// Convert `uint256` to `CrossAccountId`.66pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId67where68	T::AccountId: From<[u8; 32]>,69{70	let mut new_admin_arr = [0_u8; 32];71	from.to_big_endian(&mut new_admin_arr);72	let account_id = T::AccountId::from(new_admin_arr);73	T::CrossAccountId::from_sub(account_id)74}7576/// Convert `CrossAccountId` to `(address, uint256)`.77pub fn convert_cross_account_to_tuple<T: Config>(78	cross_account_id: &T::CrossAccountId,79) -> (address, uint256)80where81	T::AccountId: AsRef<[u8; 32]>,82{83	if cross_account_id.is_canonical_substrate() {84		let sub = convert_cross_account_to_uint256::<T>(cross_account_id);85		(Default::default(), sub)86	} else {87		let eth = *cross_account_id.as_eth();88		(eth, Default::default())89	}90}9192/// Convert tuple `(address, uint256)` to `CrossAccountId`.93///94/// If `address` in the tuple has *default* value, then the canonical form is substrate,95/// if `uint256` has *default* value, then the ethereum form is canonical,96/// if both values are *default* or *non default*, then this is considered an invalid address and `Error` is returned.97pub fn convert_tuple_to_cross_account<T: Config>(98	eth_cross_account_id: (address, uint256),99) -> evm_coder::execution::Result<T::CrossAccountId>100where101	T::AccountId: From<[u8; 32]>,102{103	if eth_cross_account_id == Default::default() {104		Err("All fields of cross account is zeroed".into())105	} else if eth_cross_account_id.0 == Default::default() {106		Ok(convert_uint256_to_cross_account::<T>(107			eth_cross_account_id.1,108		))109	} else if eth_cross_account_id.1 == Default::default() {110		Ok(T::CrossAccountId::from_eth(eth_cross_account_id.0))111	} else {112		Err("All fields of cross account is non zeroed".into())113	}114}115116/// Cross account struct117#[derive(Debug, Default, AbiCoder)]118pub struct EthCrossAccount {119	pub(crate) eth: address,120	pub(crate) sub: uint256,121}122123impl EthCrossAccount {124	pub fn from_sub_cross_account<T>(cross_account_id: &T::CrossAccountId) -> Self125	where126		T: pallet_evm::account::Config,127		T::AccountId: AsRef<[u8; 32]>,128	{129		if cross_account_id.is_canonical_substrate() {130			Self {131				eth: Default::default(),132				sub: convert_cross_account_to_uint256::<T>(cross_account_id),133			}134		} else {135			Self {136				eth: *cross_account_id.as_eth(),137				sub: Default::default(),138			}139		}140	}141142	pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>143	where144		T: pallet_evm::account::Config,145		T::AccountId: From<[u8; 32]>,146	{147		if self.eth == Default::default() && self.sub == Default::default() {148			Err("All fields of cross account is zeroed".into())149		} else if self.eth == Default::default() {150			Ok(convert_uint256_to_cross_account::<T>(self.sub))151		} else if self.sub == Default::default() {152			Ok(T::CrossAccountId::from_eth(self.eth))153		} else {154			Err("All fields of cross account is non zeroed".into())155		}156	}157}