use fuel_types::AssetId;
use fuels_macros::{Parameterize, Tokenizable, TryFrom};
use crate::types::errors::Result;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Bits256(pub [u8; 32]);
impl Bits256 {
pub fn zeroed() -> Self {
Self([0; 32])
}
pub fn from_hex_str(hex: &str) -> Result<Self> {
let hex = if let Some(stripped_hex) = hex.strip_prefix("0x") {
stripped_hex
} else {
hex
};
let mut bytes = [0u8; 32];
hex::decode_to_slice(hex, &mut bytes as &mut [u8])?;
Ok(Bits256(bytes))
}
}
impl From<AssetId> for Bits256 {
fn from(value: AssetId) -> Self {
Self(value.into())
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, Parameterize, Tokenizable, TryFrom)]
#[FuelsCorePath = "crate"]
#[FuelsTypesPath = "crate::types"]
pub struct B512 {
pub bytes: [Bits256; 2],
}
impl From<(Bits256, Bits256)> for B512 {
fn from(bits_tuple: (Bits256, Bits256)) -> Self {
B512 {
bytes: [bits_tuple.0, bits_tuple.1],
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, Parameterize, Tokenizable, TryFrom)]
#[FuelsCorePath = "crate"]
#[FuelsTypesPath = "crate::types"]
pub struct EvmAddress {
value: Bits256,
}
impl EvmAddress {
fn new(b256: Bits256) -> Self {
Self {
value: Bits256(Self::clear_12_bytes(b256.0)),
}
}
pub fn value(&self) -> Bits256 {
self.value
}
fn clear_12_bytes(bytes: [u8; 32]) -> [u8; 32] {
let mut bytes = bytes;
bytes[..12].copy_from_slice(&[0u8; 12]);
bytes
}
}
impl From<Bits256> for EvmAddress {
fn from(b256: Bits256) -> Self {
EvmAddress::new(b256)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
traits::{Parameterize, Tokenizable},
types::{param_types::ParamType, Token},
};
#[test]
fn from_hex_str_b256() -> Result<()> {
let hex_str = "0101010101010101010101010101010101010101010101010101010101010101";
let bits256 = Bits256::from_hex_str(hex_str)?;
assert_eq!(bits256.0, [1u8; 32]);
let hex_str = "0x0101010101010101010101010101010101010101010101010101010101010101";
let bits256 = Bits256::from_hex_str(hex_str)?;
assert_eq!(bits256.0, [1u8; 32]);
Ok(())
}
#[test]
fn test_param_type_evm_addr() {
assert_eq!(
EvmAddress::param_type(),
ParamType::Struct {
name: "EvmAddress".to_string(),
fields: vec![("value".to_string(), ParamType::B256)],
generics: vec![]
}
);
}
#[test]
fn evm_address_clears_first_12_bytes() -> Result<()> {
let data = [1u8; 32];
let address = EvmAddress::new(Bits256(data));
let expected_data = Bits256([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1,
]);
assert_eq!(address.value(), expected_data);
Ok(())
}
#[test]
fn test_into_token_evm_addr() {
let bits = [1u8; 32];
let evm_address = EvmAddress::from(Bits256(bits));
let token = evm_address.into_token();
let expected_data = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1,
];
assert_eq!(token, Token::Struct(vec![Token::B256(expected_data)]));
}
}