multiversx_chain_core/types/
address.rs

1use super::H256;
2use alloc::{boxed::Box, vec::Vec};
3use core::fmt::Debug;
4
5const SC_ADDRESS_NUM_LEADING_ZEROS: u8 = 8;
6pub const NUM_INT_CHARACTERS_FOR_ADDRESS: usize = 10;
7pub const VM_TYPE_LEN: usize = 2;
8pub const DEFAULT_VM_TYPE: &[u8] = &[5, 0];
9
10/// An Address is just a H256 with a different name.
11/// Has a different ABI name than H256.
12///
13/// Note: we are currently using ManagedAddress in contracts.
14/// While this also works, its use in contracts is discouraged.
15#[derive(Hash, PartialEq, Eq, Clone, Debug)]
16pub struct Address(H256);
17
18impl Address {
19    pub const fn new(bytes: [u8; 32]) -> Self {
20        Address(H256::new(bytes))
21    }
22
23    pub fn generate_mock_address(creator_address: &[u8], creator_nonce: u64) -> Self {
24        let mut result = [0x00; 32];
25
26        result[10] = 0x11;
27        result[11] = 0x11;
28        result[12] = 0x11;
29        result[13] = 0x11;
30
31        result[14..29].copy_from_slice(&creator_address[..15]);
32        result[29] = creator_nonce as u8;
33        result[30..].copy_from_slice(&creator_address[30..]);
34
35        let start_index = NUM_INT_CHARACTERS_FOR_ADDRESS - VM_TYPE_LEN;
36        result[start_index..(start_index + DEFAULT_VM_TYPE.len())].copy_from_slice(DEFAULT_VM_TYPE);
37
38        Address::from(result)
39    }
40
41    #[cfg(feature = "std")]
42    pub fn to_bech32(&self, hrp: &str) -> crate::std::Bech32Address {
43        crate::std::Bech32Address::encode_address(hrp, self.clone())
44    }
45
46    #[cfg(feature = "std")]
47    pub fn to_bech32_default(&self) -> crate::std::Bech32Address {
48        crate::std::Bech32Address::encode_address_default_hrp(self.clone())
49    }
50
51    #[cfg(feature = "std")]
52    pub fn to_hex(&self) -> String {
53        self.0.to_hex()
54    }
55}
56
57impl From<H256> for Address {
58    #[inline]
59    fn from(hash: H256) -> Self {
60        Address(hash)
61    }
62}
63
64impl From<Address> for H256 {
65    #[inline]
66    fn from(address: Address) -> Self {
67        address.0
68    }
69}
70
71impl<'a> From<&'a Address> for &'a H256 {
72    #[inline]
73    fn from(address: &'a Address) -> Self {
74        &address.0
75    }
76}
77
78impl From<[u8; 32]> for Address {
79    #[inline]
80    fn from(arr: [u8; 32]) -> Self {
81        Address(H256::from(arr))
82    }
83}
84
85impl<'a> From<&'a [u8; 32]> for Address {
86    #[inline]
87    fn from(bytes: &'a [u8; 32]) -> Self {
88        Address(H256::from(bytes))
89    }
90}
91
92impl<'a> From<&'a mut [u8; 32]> for Address {
93    #[inline]
94    fn from(bytes: &'a mut [u8; 32]) -> Self {
95        Address(H256::from(bytes))
96    }
97}
98
99impl From<Box<[u8; 32]>> for Address {
100    #[inline]
101    fn from(bytes: Box<[u8; 32]>) -> Self {
102        Address(H256::from(bytes))
103    }
104}
105
106impl Address {
107    pub fn from_slice(slice: &[u8]) -> Self {
108        Address(H256::from_slice(slice))
109    }
110}
111
112impl From<Address> for [u8; 32] {
113    #[inline]
114    fn from(addr: Address) -> Self {
115        addr.0.into()
116    }
117}
118
119impl AsRef<[u8]> for Address {
120    #[inline]
121    fn as_ref(&self) -> &[u8] {
122        self.0.as_ref()
123    }
124}
125
126impl AsMut<[u8]> for Address {
127    #[inline]
128    fn as_mut(&mut self) -> &mut [u8] {
129        self.0.as_mut()
130    }
131}
132
133impl Address {
134    /// Returns a new address of 32 zeros.
135    /// Allocates directly in heap.
136    /// Minimal resulting wasm code (14 bytes if not inlined).
137    pub fn zero() -> Self {
138        Address(H256::zero())
139    }
140
141    /// Returns the size of an address in bytes.
142    #[inline]
143    pub fn len_bytes() -> usize {
144        H256::len_bytes()
145    }
146
147    /// Extracts a byte slice containing the entire fixed hash.
148    #[inline]
149    pub fn as_bytes(&self) -> &[u8] {
150        self.0.as_bytes()
151    }
152
153    #[inline]
154    pub fn as_array(&self) -> &[u8; 32] {
155        self.0.as_array()
156    }
157
158    #[inline]
159    pub fn copy_to_array(&self, target: &mut [u8; 32]) {
160        self.0.copy_to_array(target)
161    }
162
163    #[inline]
164    pub fn to_vec(&self) -> Vec<u8> {
165        self.0.to_vec()
166    }
167
168    /// Pointer to the data on the heap.
169    #[inline]
170    pub fn as_ptr(&self) -> *const u8 {
171        self.0.as_ptr()
172    }
173
174    /// Returns an unsafe mutable pointer to the data on the heap.
175    /// Used by the API to populate data.
176    #[inline]
177    pub fn as_mut_ptr(&mut self) -> *mut u8 {
178        self.0.as_mut_ptr()
179    }
180
181    /// True if all 32 bytes of the hash are zero.
182    pub fn is_zero(&self) -> bool {
183        self.0.is_zero()
184    }
185
186    pub fn is_smart_contract_address(&self) -> bool {
187        self.as_bytes()
188            .iter()
189            .take(SC_ADDRESS_NUM_LEADING_ZEROS.into())
190            .all(|item| item == &0u8)
191    }
192}
193
194use crate::codec::*;
195
196impl NestedEncode for Address {
197    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
198    where
199        O: NestedEncodeOutput,
200        H: EncodeErrorHandler,
201    {
202        self.0.dep_encode_or_handle_err(dest, h)
203    }
204}
205
206impl TopEncode for Address {
207    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
208    where
209        O: TopEncodeOutput,
210        H: EncodeErrorHandler,
211    {
212        self.0.top_encode_or_handle_err(output, h)
213    }
214}
215
216impl NestedDecode for Address {
217    fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
218    where
219        I: NestedDecodeInput,
220        H: DecodeErrorHandler,
221    {
222        Ok(Address(H256::dep_decode_or_handle_err(input, h)?))
223    }
224}
225
226impl TopDecode for Address {
227    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
228    where
229        I: TopDecodeInput,
230        H: DecodeErrorHandler,
231    {
232        Ok(Address(H256::top_decode_or_handle_err(input, h)?))
233    }
234}
235
236#[cfg(feature = "std")]
237impl core::fmt::Display for Address {
238    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
239        core::fmt::Display::fmt(&self.to_hex(), f)
240    }
241}
242
243#[cfg(test)]
244mod address_tests {
245    use super::*;
246    use crate::codec::test_util::{check_top_encode, check_top_encode_decode};
247    use alloc::vec::Vec;
248
249    #[test]
250    fn test_address() {
251        let addr = Address::from([4u8; 32]);
252        check_top_encode_decode(addr, &[4u8; 32]);
253    }
254
255    #[test]
256    fn test_opt_address() {
257        let addr = Address::from([4u8; 32]);
258        let mut expected: Vec<u8> = Vec::new();
259        expected.push(1u8);
260        expected.extend_from_slice(&[4u8; 32]);
261        check_top_encode_decode(Some(addr), expected.as_slice());
262    }
263
264    #[test]
265    fn test_ser_address_ref() {
266        let addr = Address::from([4u8; 32]);
267        let expected_bytes: &[u8] = &[4u8; 32 * 3];
268
269        let tuple = (&addr, &&&addr, addr.clone());
270        let serialized_bytes = check_top_encode(&tuple);
271        assert_eq!(serialized_bytes.as_slice(), expected_bytes);
272    }
273
274    #[test]
275    fn test_is_zero() {
276        assert!(Address::zero().is_zero());
277    }
278}