Skip to content

Commit a154e1d

Browse files
authored
feat: initialize EthAddress from bytes (#506)
1 parent bedaa37 commit a154e1d

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

starknet-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ sha3 = { version = "0.10.7", default-features = false }
3030

3131
[dev-dependencies]
3232
criterion = { version = "0.4.0", default-features = false }
33+
hex-literal = "0.4.1"
3334
starknet-core = { path = ".", features = ["no_unknown_fields"] }
3435

3536
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]

starknet-core/src/types/eth_address.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@ mod errors {
3131
#[derive(Debug)]
3232
pub struct FromFieldElementError;
3333

34+
#[derive(Debug)]
35+
pub struct FromBytesSliceError;
36+
3437
#[cfg(feature = "std")]
3538
impl std::error::Error for FromHexError {}
3639

3740
#[cfg(feature = "std")]
3841
impl std::error::Error for FromFieldElementError {}
3942

43+
#[cfg(feature = "std")]
44+
impl std::error::Error for FromBytesSliceError {}
45+
4046
impl Display for FromHexError {
4147
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
4248
match self {
@@ -55,8 +61,14 @@ mod errors {
5561
write!(f, "FieldElement value out of range")
5662
}
5763
}
64+
65+
impl Display for FromBytesSliceError {
66+
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
67+
write!(f, "invalid slice for ETH address")
68+
}
69+
}
5870
}
59-
pub use errors::{FromFieldElementError, FromHexError};
71+
pub use errors::{FromBytesSliceError, FromFieldElementError, FromHexError};
6072

6173
impl EthAddress {
6274
pub fn from_hex(hex: &str) -> Result<Self, FromHexError> {
@@ -156,3 +168,66 @@ impl From<EthAddress> for FieldElement {
156168
FieldElement::from_byte_slice_be(&value.inner).unwrap()
157169
}
158170
}
171+
172+
impl TryFrom<&[u8]> for EthAddress {
173+
type Error = FromBytesSliceError;
174+
175+
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
176+
if value.len() != 20 {
177+
Err(FromBytesSliceError)
178+
} else {
179+
// Safe to unwrap as we know length is 20.
180+
Ok(Self {
181+
inner: value.try_into().unwrap(),
182+
})
183+
}
184+
}
185+
}
186+
187+
impl From<[u8; 20]> for EthAddress {
188+
fn from(value: [u8; 20]) -> Self {
189+
Self { inner: value }
190+
}
191+
}
192+
193+
#[cfg(test)]
194+
mod tests {
195+
use hex_literal::hex;
196+
197+
use super::EthAddress;
198+
199+
#[test]
200+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
201+
fn test_eth_address_from_bytes_array() {
202+
let address_bytes: [u8; 20] = hex!("e7f1725e7734ce288f8367e1bb143e90bb3f0512");
203+
204+
let eth_address: EthAddress = address_bytes.into();
205+
assert_eq!(
206+
EthAddress::from_hex("0xe7f1725e7734ce288f8367e1bb143e90bb3f0512").unwrap(),
207+
eth_address
208+
);
209+
}
210+
211+
#[test]
212+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
213+
fn test_eth_address_from_slice() {
214+
// address: e7f1725e7734ce288f8367e1bb143e90bb3f0512, inside a buffer with more data.
215+
let buffer = hex!("010203e7f1725e7734ce288f8367e1bb143e90bb3f0512");
216+
217+
let eth_address: EthAddress = (&buffer[3..23])
218+
.try_into()
219+
.expect("failed to get EthAddress from slice");
220+
assert_eq!(
221+
EthAddress::from_hex("0xe7f1725e7734ce288f8367e1bb143e90bb3f0512").unwrap(),
222+
eth_address
223+
);
224+
}
225+
226+
#[test]
227+
#[should_panic(expected = "FromBytesSliceError")]
228+
fn test_eth_address_from_slice_invalid_slice() {
229+
let buffer: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7];
230+
231+
EthAddress::try_from(&buffer[0..4]).unwrap();
232+
}
233+
}

0 commit comments

Comments
 (0)