revm_interpreter/instructions/
utility.rs

1use primitives::{Address, B256, U256};
2
3/// Pushes an arbitrary length slice of bytes onto the stack, padding the last word with zeros
4/// if necessary.
5///
6/// # Panics
7///
8/// Panics if slice is longer than 32 bytes.
9#[inline]
10pub fn cast_slice_to_u256(slice: &[u8], dest: &mut U256) {
11    if slice.is_empty() {
12        return;
13    }
14    assert!(slice.len() <= 32, "slice too long");
15
16    let n_words = slice.len().div_ceil(32);
17
18    // SAFETY: Length checked above.
19    unsafe {
20        //let dst = self.data.as_mut_ptr().add(self.data.len()).cast::<u64>();
21        //self.data.set_len(new_len);
22        let dst = dest.as_limbs_mut().as_mut_ptr();
23
24        let mut i = 0;
25
26        // Write full words
27        let words = slice.chunks_exact(32);
28        let partial_last_word = words.remainder();
29        for word in words {
30            // Note: We unroll `U256::from_be_bytes` here to write directly into the buffer,
31            // instead of creating a 32 byte array on the stack and then copying it over.
32            for l in word.rchunks_exact(8) {
33                dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
34                i += 1;
35            }
36        }
37
38        if partial_last_word.is_empty() {
39            return;
40        }
41
42        // Write limbs of partial last word
43        let limbs = partial_last_word.rchunks_exact(8);
44        let partial_last_limb = limbs.remainder();
45        for l in limbs {
46            dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
47            i += 1;
48        }
49
50        // Write partial last limb by padding with zeros
51        if !partial_last_limb.is_empty() {
52            let mut tmp = [0u8; 8];
53            tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb);
54            dst.add(i).write(u64::from_be_bytes(tmp));
55            i += 1;
56        }
57
58        debug_assert_eq!(i.div_ceil(4), n_words, "wrote too much");
59
60        // Zero out upper bytes of last word
61        let m = i % 4; // 32 / 8
62        if m != 0 {
63            dst.add(i).write_bytes(0, 4 - m);
64        }
65    }
66}
67
68pub trait IntoU256 {
69    fn into_u256(self) -> U256;
70}
71
72impl IntoU256 for Address {
73    fn into_u256(self) -> U256 {
74        self.into_word().into_u256()
75    }
76}
77
78impl IntoU256 for B256 {
79    fn into_u256(self) -> U256 {
80        U256::from_be_bytes(self.0)
81    }
82}
83
84pub trait IntoAddress {
85    fn into_address(self) -> Address;
86}
87
88impl IntoAddress for U256 {
89    fn into_address(self) -> Address {
90        Address::from_word(B256::from(self.to_be_bytes()))
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use primitives::address;
97
98    use super::*;
99
100    #[test]
101    fn test_into_u256() {
102        let addr = address!("0x0000000000000000000000000000000000000001");
103        let u256 = addr.into_u256();
104        assert_eq!(u256, U256::from(0x01));
105        assert_eq!(u256.into_address(), addr);
106    }
107}