evm_interpreter/
utils.rs

1//! Small utilities.
2
3use core::{
4	cmp::Ordering,
5	ops::{Div, Rem},
6};
7
8use primitive_types::{H160, H256, U256};
9
10use crate::error::{ExitError, ExitFatal};
11
12/// Convert [U256] into [H256].
13#[must_use]
14pub fn u256_to_h256(v: U256) -> H256 {
15	let mut r = H256::default();
16	v.to_big_endian(&mut r[..]);
17	r
18}
19
20/// Convert [H256] to [U256].
21#[must_use]
22pub fn h256_to_u256(v: H256) -> U256 {
23	U256::from_big_endian(&v[..])
24}
25
26/// Convert [U256] into [H160]
27#[must_use]
28pub fn u256_to_h160(v: U256) -> H160 {
29	u256_to_h256(v).into()
30}
31
32/// Convert [U256] to [usize].
33pub fn u256_to_usize(v: U256) -> Result<usize, ExitError> {
34	if v > U256::from(usize::MAX) {
35		return Err(ExitFatal::NotSupported.into());
36	}
37	Ok(v.as_usize())
38}
39
40/// Sign of [I256].
41#[derive(Copy, Clone, Eq, PartialEq, Debug)]
42pub enum Sign {
43	Plus,
44	Minus,
45	Zero,
46}
47
48const SIGN_BIT_MASK: U256 = U256([
49	0xffff_ffff_ffff_ffff,
50	0xffff_ffff_ffff_ffff,
51	0xffff_ffff_ffff_ffff,
52	0x7fff_ffff_ffff_ffff,
53]);
54
55/// Signed 256-bit integer.
56#[derive(Copy, Clone, Eq, PartialEq, Debug)]
57pub struct I256(pub Sign, pub U256);
58
59impl I256 {
60	/// Zero value of I256.
61	#[must_use]
62	pub const fn zero() -> I256 {
63		I256(Sign::Zero, U256::zero())
64	}
65	/// Minimum value of I256.
66	#[must_use]
67	pub fn min_value() -> I256 {
68		I256(Sign::Minus, (U256::MAX & SIGN_BIT_MASK) + U256::from(1u64))
69	}
70}
71
72impl Ord for I256 {
73	fn cmp(&self, other: &I256) -> Ordering {
74		match (self.0, other.0) {
75			(Sign::Zero, Sign::Zero) => Ordering::Equal,
76			(Sign::Zero, Sign::Plus) => Ordering::Less,
77			(Sign::Zero, Sign::Minus) => Ordering::Greater,
78			(Sign::Minus, Sign::Zero) => Ordering::Less,
79			(Sign::Minus, Sign::Plus) => Ordering::Less,
80			(Sign::Minus, Sign::Minus) => self.1.cmp(&other.1).reverse(),
81			(Sign::Plus, Sign::Minus) => Ordering::Greater,
82			(Sign::Plus, Sign::Zero) => Ordering::Greater,
83			(Sign::Plus, Sign::Plus) => self.1.cmp(&other.1),
84		}
85	}
86}
87
88impl PartialOrd for I256 {
89	fn partial_cmp(&self, other: &I256) -> Option<Ordering> {
90		Some(self.cmp(other))
91	}
92}
93
94impl Default for I256 {
95	fn default() -> I256 {
96		I256::zero()
97	}
98}
99
100impl From<U256> for I256 {
101	fn from(val: U256) -> I256 {
102		if val == U256::zero() {
103			I256::zero()
104		} else if val & SIGN_BIT_MASK == val {
105			I256(Sign::Plus, val)
106		} else {
107			I256(Sign::Minus, !val + U256::from(1u64))
108		}
109	}
110}
111
112impl From<I256> for U256 {
113	fn from(value: I256) -> U256 {
114		let sign = value.0;
115		if sign == Sign::Zero {
116			U256::zero()
117		} else if sign == Sign::Plus {
118			value.1
119		} else {
120			!value.1 + U256::from(1u64)
121		}
122	}
123}
124
125impl Div for I256 {
126	type Output = I256;
127
128	fn div(self, other: I256) -> I256 {
129		if other == I256::zero() {
130			return I256::zero();
131		}
132
133		if self == I256::min_value() && other.1 == U256::from(1u64) {
134			return I256::min_value();
135		}
136
137		let d = (self.1 / other.1) & SIGN_BIT_MASK;
138
139		if d == U256::zero() {
140			return I256::zero();
141		}
142
143		match (self.0, other.0) {
144			(Sign::Zero, Sign::Plus)
145			| (Sign::Plus, Sign::Zero)
146			| (Sign::Zero, Sign::Zero)
147			| (Sign::Plus, Sign::Plus)
148			| (Sign::Minus, Sign::Minus) => I256(Sign::Plus, d),
149			(Sign::Zero, Sign::Minus)
150			| (Sign::Plus, Sign::Minus)
151			| (Sign::Minus, Sign::Zero)
152			| (Sign::Minus, Sign::Plus) => I256(Sign::Minus, d),
153		}
154	}
155}
156
157impl Rem for I256 {
158	type Output = I256;
159
160	fn rem(self, other: I256) -> I256 {
161		let r = (self.1 % other.1) & SIGN_BIT_MASK;
162
163		if r == U256::zero() {
164			return I256::zero();
165		}
166
167		I256(self.0, r)
168	}
169}
170
171#[cfg(test)]
172mod tests {
173	use std::num::Wrapping;
174
175	use super::*;
176
177	#[test]
178	fn div_i256() {
179		// Sanity checks based on i8. Notice that we need to use `Wrapping` here because
180		// Rust will prevent the overflow by default whereas the EVM does not.
181		assert_eq!(Wrapping(i8::MIN) / Wrapping(-1), Wrapping(i8::MIN));
182
183		assert_eq!(100i8 / -1, -100i8);
184		assert_eq!(100i8 / 2, 50i8);
185
186		// Now the same calculations based on i256
187		let one = I256(Sign::Zero, U256::from(1));
188		let one_hundred = I256(Sign::Zero, U256::from(100));
189		let fifty = I256(Sign::Plus, U256::from(50));
190		let two = I256(Sign::Zero, U256::from(2));
191		let neg_one_hundred = I256(Sign::Minus, U256::from(100));
192		let minus_one = I256(Sign::Minus, U256::from(1));
193		let max_value = I256(Sign::Plus, U256::from(2).pow(U256::from(255)) - 1);
194		let neg_max_value = I256(Sign::Minus, U256::from(2).pow(U256::from(255)) - 1);
195
196		assert_eq!(I256::min_value() / minus_one, I256::min_value());
197		assert_eq!(I256::min_value() / one, I256::min_value());
198		assert_eq!(max_value / one, max_value);
199		assert_eq!(max_value / minus_one, neg_max_value);
200
201		assert_eq!(one_hundred / minus_one, neg_one_hundred);
202		assert_eq!(one_hundred / two, fifty);
203	}
204}