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

difftreelog

feat Add AbiWrite support for vec with dynamic type

Trubnikov Sergey2022-10-24parent: #88bc48d.patch.diff
in: master

6 files changed

modifiedcrates/evm-coder/Cargo.tomldiffbeforeafterboth
--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -22,6 +22,7 @@
 # We want to assert some large binary blobs equality in tests
 hex = "0.4.3"
 hex-literal = "0.3.4"
+similar-asserts = "1.4.2"
 
 [features]
 default = ["std"]
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi.rs
+++ b/crates/evm-coder/src/abi.rs
@@ -25,7 +25,7 @@
 
 use crate::{
 	execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},
-	types::{string, self},
+	types::*,
 };
 use crate::execution::Result;
 
@@ -56,7 +56,7 @@
 		}
 	}
 	/// Start reading RLP buffer, parsing first 4 bytes as selector
-	pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {
+	pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {
 		if buf.len() < 4 {
 			return Err(Error::Error(ExitError::OutOfOffset));
 		}
@@ -252,11 +252,11 @@
 		self.static_part.extend(block);
 	}
 
-	fn write_padright(&mut self, bytes: &[u8]) {
-		assert!(bytes.len() <= ABI_ALIGNMENT);
-		self.static_part.extend(bytes);
+	fn write_padright(&mut self, block: &[u8]) {
+		assert!(block.len() <= ABI_ALIGNMENT);
+		self.static_part.extend(block);
 		self.static_part
-			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);
+			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);
 	}
 
 	/// Write [`H160`] to end of buffer
@@ -369,16 +369,30 @@
 	};
 }
 
-impl_abi_readable!(u8, uint8, false);
-impl_abi_readable!(u32, uint32, false);
-impl_abi_readable!(u64, uint64, false);
-impl_abi_readable!(u128, uint128, false);
-impl_abi_readable!(U256, uint256, false);
-impl_abi_readable!([u8; 4], bytes4, false);
-impl_abi_readable!(H160, address, false);
-impl_abi_readable!(Vec<u8>, bytes, true);
-impl_abi_readable!(bool, bool, true);
+impl_abi_readable!(bool, bool, false);
+impl_abi_readable!(uint8, uint8, false);
+impl_abi_readable!(uint32, uint32, false);
+impl_abi_readable!(uint64, uint64, false);
+impl_abi_readable!(uint128, uint128, false);
+impl_abi_readable!(uint256, uint256, false);
+impl_abi_readable!(bytes4, bytes4, false);
+impl_abi_readable!(address, address, false);
 impl_abi_readable!(string, string, true);
+// impl_abi_readable!(bytes, bytes, true);
+
+impl TypeHelper for bytes {
+	fn is_dynamic() -> bool {
+		true
+	}
+	fn size() -> usize {
+		ABI_ALIGNMENT
+	}
+}
+impl AbiRead<bytes> for AbiReader<'_> {
+	fn abi_read(&mut self) -> Result<bytes> {
+		Ok(bytes(self.bytes()?))
+	}
+}
 
 mod sealed {
 	/// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead
@@ -524,17 +538,19 @@
 impl_abi_writeable!(H160, address);
 impl_abi_writeable!(bool, bool);
 impl_abi_writeable!(&str, string);
+
 impl AbiWrite for string {
 	fn abi_write(&self, writer: &mut AbiWriter) {
 		writer.string(self)
 	}
 }
-// impl AbiWrite for Vec<u8> {
-// 	fn abi_write(&self, writer: &mut AbiWriter) {
-// 		writer.bytes(self)
-// 	}
-// }
 
+impl AbiWrite for bytes {
+	fn abi_write(&self, writer: &mut AbiWriter) {
+		writer.bytes(self.0.as_slice())
+	}
+}
+
 impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {
 	fn abi_write(&self, writer: &mut AbiWriter) {
 		let is_dynamic = T::is_dynamic();
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -133,8 +133,10 @@
 	pub type string = ::alloc::string::String;
 	#[cfg(feature = "std")]
 	pub type string = ::std::string::String;
-	pub type bytes = Vec<u8>;
 
+	#[derive(Default, Debug)]
+	pub struct bytes(pub Vec<u8>);
+
 	/// Solidity doesn't have `void` type, however we have special implementation
 	/// for empty tuple return type
 	pub type void = ();
@@ -157,6 +159,30 @@
 		/// and there is no `receiver()` function defined.
 		pub value: U256,
 	}
+
+	impl From<Vec<u8>> for bytes {
+		fn from(src: Vec<u8>) -> Self {
+			Self(src)
+		}
+	}
+
+	impl Into<Vec<u8>> for bytes {
+		fn into(self) -> Vec<u8> {
+			self.0
+		}
+	}
+
+	impl bytes {
+		#[must_use]
+		pub fn len(&self) -> usize {
+			self.0.len()
+		}
+
+		#[must_use]
+		pub fn is_empty(&self) -> bool {
+			self.len() == 0
+		}
+	}
 }
 
 /// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -85,7 +85,7 @@
 		let key = <Vec<u8>>::from(key)
 			.try_into()
 			.map_err(|_| "key too large")?;
-		let value = value.try_into().map_err(|_| "value too large")?;
+		let value = value.0.try_into().map_err(|_| "value too large")?;
 
 		<Pallet<T>>::set_collection_property(self, &caller, Property { key, value })
 			.map_err(dispatch_to_evm::<T>)
@@ -120,7 +120,7 @@
 		let props = <CollectionProperties<T>>::get(self.id);
 		let prop = props.get(&key).ok_or("key not found")?;
 
-		Ok(prop.to_vec())
+		Ok(bytes(prop.to_vec()))
 	}
 
 	/// Set the sponsor of the collection.
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -97,7 +97,7 @@
 		let key = <Vec<u8>>::from(key)
 			.try_into()
 			.map_err(|_| "key too long")?;
-		let value = value.try_into().map_err(|_| "value too long")?;
+		let value = value.0.try_into().map_err(|_| "value too long")?;
 
 		let nesting_budget = self
 			.recorder
@@ -146,7 +146,7 @@
 		let props = <TokenProperties<T>>::get((self.id, token_id));
 		let prop = props.get(&key).ok_or("key not found")?;
 
-		Ok(prop.to_vec())
+		Ok(prop.to_vec().into())
 	}
 }
 
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
100 let key = <Vec<u8>>::from(key)100 let key = <Vec<u8>>::from(key)
101 .try_into()101 .try_into()
102 .map_err(|_| "key too long")?;102 .map_err(|_| "key too long")?;
103 let value = value.try_into().map_err(|_| "value too long")?;103 let value = value.0.try_into().map_err(|_| "value too long")?;
104104
105 let nesting_budget = self105 let nesting_budget = self
106 .recorder106 .recorder
149 let props = <TokenProperties<T>>::get((self.id, token_id));149 let props = <TokenProperties<T>>::get((self.id, token_id));
150 let prop = props.get(&key).ok_or("key not found")?;150 let prop = props.get(&key).ok_or("key not found")?;
151151
152 Ok(prop.to_vec())152 Ok(prop.to_vec().into())
153 }153 }
154}154}
155155