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