difftreelog
feat Add AbiWrite support for vec with dynamic type
in: master
6 files changed
crates/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"]
crates/evm-coder/src/abi.rsdiffbeforeafterboth252526use crate::{26use crate::{27 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},27 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},28 types::{string, self},28 types::*,29};29};30use crate::execution::Result;30use crate::execution::Result;313156 }56 }57 }57 }58 /// Start reading RLP buffer, parsing first 4 bytes as selector58 /// Start reading RLP buffer, parsing first 4 bytes as selector59 pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {59 pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {60 if buf.len() < 4 {60 if buf.len() < 4 {61 return Err(Error::Error(ExitError::OutOfOffset));61 return Err(Error::Error(ExitError::OutOfOffset));62 }62 }252 self.static_part.extend(block);252 self.static_part.extend(block);253 }253 }254254255 fn write_padright(&mut self, bytes: &[u8]) {255 fn write_padright(&mut self, block: &[u8]) {256 assert!(bytes.len() <= ABI_ALIGNMENT);256 assert!(block.len() <= ABI_ALIGNMENT);257 self.static_part.extend(bytes);257 self.static_part.extend(block);258 self.static_part258 self.static_part259 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);259 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);260 }260 }261261262 /// Write [`H160`] to end of buffer262 /// Write [`H160`] to end of buffer369 };369 };370}370}371371372impl_abi_readable!(bool, bool, false);372impl_abi_readable!(u8, uint8, false);373impl_abi_readable!(uint8, uint8, false);373impl_abi_readable!(u32, uint32, false);374impl_abi_readable!(uint32, uint32, false);374impl_abi_readable!(u64, uint64, false);375impl_abi_readable!(uint64, uint64, false);375impl_abi_readable!(u128, uint128, false);376impl_abi_readable!(uint128, uint128, false);376impl_abi_readable!(U256, uint256, false);377impl_abi_readable!(uint256, uint256, false);377impl_abi_readable!([u8; 4], bytes4, false);378impl_abi_readable!(bytes4, bytes4, false);378impl_abi_readable!(H160, address, false);379impl_abi_readable!(address, address, false);379impl_abi_readable!(Vec<u8>, bytes, true);380impl_abi_readable!(bool, bool, true);381impl_abi_readable!(string, string, true);380impl_abi_readable!(string, string, true);381// impl_abi_readable!(bytes, bytes, true);382383impl TypeHelper for bytes {384 fn is_dynamic() -> bool {385 true386 }387 fn size() -> usize {388 ABI_ALIGNMENT389 }390}391impl AbiRead<bytes> for AbiReader<'_> {392 fn abi_read(&mut self) -> Result<bytes> {393 Ok(bytes(self.bytes()?))394 }395}382396383mod sealed {397mod sealed {384 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead398 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead529 writer.string(self)544 writer.string(self)530 }545 }531}546}532// impl AbiWrite for Vec<u8> {547533// fn abi_write(&self, writer: &mut AbiWriter) {548impl AbiWrite for bytes {534// writer.bytes(self)549 fn abi_write(&self, writer: &mut AbiWriter) {535// }550 writer.bytes(self.0.as_slice())536// }551 }552}537553538impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {554impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {539 fn abi_write(&self, writer: &mut AbiWriter) {555 fn abi_write(&self, writer: &mut AbiWriter) {crates/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
pallets/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.
pallets/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())
}
}
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -100,7 +100,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
@@ -149,7 +149,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())
}
}