1#[cfg(not(target_arch = "wasm32"))]
3mod ganache;
4#[cfg(not(target_arch = "wasm32"))]
5pub use ganache::{Ganache, GanacheInstance};
6
7#[cfg(not(target_arch = "wasm32"))]
9mod geth;
10#[cfg(not(target_arch = "wasm32"))]
11pub use geth::{Geth, GethInstance};
12
13mod genesis;
15pub use genesis::{ChainConfig, CliqueConfig, EthashConfig, Genesis, GenesisAccount};
16
17#[cfg(not(target_arch = "wasm32"))]
19mod anvil;
20#[cfg(not(target_arch = "wasm32"))]
21pub use anvil::{Anvil, AnvilInstance};
22
23pub mod moonbeam;
25
26mod hash;
27pub use hash::{hash_message, id, keccak256, serialize};
28
29mod units;
30use serde::{Deserialize, Deserializer};
31pub use units::Units;
32
33pub use rlp;
35
36pub use hex;
38
39use crate::types::{Address, ParseI256Error, I256, U256, U64};
40use elliptic_curve::sec1::ToEncodedPoint;
41use ethabi::ethereum_types::FromDecStrErr;
42use k256::{ecdsa::SigningKey, PublicKey as K256PublicKey};
43use std::{
44 convert::{TryFrom, TryInto},
45 fmt,
46 str::FromStr,
47};
48use thiserror::Error;
49
50const OVERFLOW_I256_UNITS: usize = 77;
52const OVERFLOW_U256_UNITS: usize = 78;
54
55#[doc(hidden)]
57pub mod __serde_json {
58 pub use serde_json::*;
59}
60
61#[derive(Error, Debug)]
62pub enum ConversionError {
63 #[error("Unknown units: {0}")]
64 UnrecognizedUnits(String),
65 #[error("bytes32 strings must not exceed 32 bytes in length")]
66 TextTooLong,
67 #[error(transparent)]
68 Utf8Error(#[from] std::str::Utf8Error),
69 #[error(transparent)]
70 InvalidFloat(#[from] std::num::ParseFloatError),
71 #[error(transparent)]
72 FromDecStrError(#[from] FromDecStrErr),
73 #[error("Overflow parsing string")]
74 ParseOverflow,
75 #[error(transparent)]
76 ParseI256Error(#[from] ParseI256Error),
77}
78
79pub const WEI_IN_ETHER: U256 = U256([0x0de0b6b3a7640000, 0x0, 0x0, 0x0]);
81
82pub const EIP1559_FEE_ESTIMATION_PAST_BLOCKS: u64 = 10;
84pub const EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE: f64 = 5.0;
86pub const EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE: u64 = 3_000_000_000;
88pub const EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER: u64 = 100_000_000_000;
91pub const EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE: i64 = 200;
94
95#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
98pub enum ParseUnits {
99 U256(U256),
100 I256(I256),
101}
102
103impl From<ParseUnits> for U256 {
104 fn from(n: ParseUnits) -> Self {
105 match n {
106 ParseUnits::U256(n) => n,
107 ParseUnits::I256(n) => n.into_raw(),
108 }
109 }
110}
111
112impl fmt::Display for ParseUnits {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 match self {
115 ParseUnits::U256(val) => val.fmt(f),
116 ParseUnits::I256(val) => val.fmt(f),
117 }
118 }
119}
120
121macro_rules! construct_format_units_from {
122 ($( $t:ty[$convert:ident] ),*) => {
123 $(
124 impl From<$t> for ParseUnits {
125 fn from(num: $t) -> Self {
126 Self::$convert(num.into())
127 }
128 }
129 )*
130 }
131}
132
133construct_format_units_from! {
135 u8[U256], u16[U256], u32[U256], u64[U256], u128[U256], U256[U256], usize[U256],
136 i8[I256], i16[I256], i32[I256], i64[I256], i128[I256], I256[I256], isize[I256]
137}
138
139pub fn format_ether<T: Into<U256>>(amount: T) -> U256 {
144 amount.into() / WEI_IN_ETHER
145}
146
147pub fn format_units<T, K>(amount: T, units: K) -> Result<String, ConversionError>
168where
169 T: Into<ParseUnits>,
170 K: TryInto<Units, Error = ConversionError>,
171{
172 let units: usize = units.try_into()?.into();
173 let amount = amount.into();
174
175 match amount {
176 ParseUnits::U256(_) if units >= OVERFLOW_U256_UNITS => {
178 return Err(ConversionError::ParseOverflow)
179 }
180 ParseUnits::I256(_) if units >= OVERFLOW_I256_UNITS => {
182 return Err(ConversionError::ParseOverflow)
183 }
184 _ => {}
185 };
186 let exp10 = U256::exp10(units);
187
188 match amount {
190 ParseUnits::U256(amount) => {
191 let integer = amount / exp10;
192 let decimals = (amount % exp10).to_string();
193 Ok(format!("{integer}.{decimals:0>units$}"))
194 }
195 ParseUnits::I256(amount) => {
196 let exp10 = I256::from_raw(exp10);
197 let sign = if amount.is_negative() { "-" } else { "" };
198 let integer = (amount / exp10).twos_complement();
199 let decimals = ((amount % exp10).twos_complement()).to_string();
200 Ok(format!("{sign}{integer}.{decimals:0>units$}"))
201 }
202 }
203}
204
205pub fn parse_ether<S: ToString>(eth: S) -> Result<U256, ConversionError> {
216 Ok(parse_units(eth, "ether")?.into())
217}
218
219pub fn parse_units<K, S>(amount: S, units: K) -> Result<ParseUnits, ConversionError>
238where
239 S: ToString,
240 K: TryInto<Units, Error = ConversionError> + Copy,
241{
242 let exponent: u32 = units.try_into()?.as_num();
243 let mut amount_str = amount.to_string().replace('_', "");
244 let negative = amount_str.chars().next().unwrap_or_default() == '-';
245 let dec_len = if let Some(di) = amount_str.find('.') {
246 amount_str.remove(di);
247 amount_str[di..].len() as u32
248 } else {
249 0
250 };
251
252 if dec_len > exponent {
253 let amount_str = &amount_str[..(amount_str.len() - (dec_len - exponent) as usize)];
255 if negative {
256 if amount_str == "-" {
259 Ok(ParseUnits::I256(I256::zero()))
260 } else {
261 Ok(ParseUnits::I256(I256::from_dec_str(amount_str)?))
262 }
263 } else {
264 Ok(ParseUnits::U256(U256::from_dec_str(amount_str)?))
265 }
266 } else if negative {
267 if amount_str == "-" {
269 Ok(ParseUnits::I256(I256::zero()))
270 } else {
271 let mut n = I256::from_dec_str(&amount_str)?;
272 n *= I256::from(10)
273 .checked_pow(exponent - dec_len)
274 .ok_or(ConversionError::ParseOverflow)?;
275 Ok(ParseUnits::I256(n))
276 }
277 } else {
278 let mut a_uint = U256::from_dec_str(&amount_str)?;
279 a_uint *= U256::from(10)
280 .checked_pow(U256::from(exponent - dec_len))
281 .ok_or(ConversionError::ParseOverflow)?;
282 Ok(ParseUnits::U256(a_uint))
283 }
284}
285
286pub fn get_contract_address(sender: impl Into<Address>, nonce: impl Into<U256>) -> Address {
290 let mut stream = rlp::RlpStream::new();
291 stream.begin_list(2);
292 stream.append(&sender.into());
293 stream.append(&nonce.into());
294
295 let hash = keccak256(&stream.out());
296
297 let mut bytes = [0u8; 20];
298 bytes.copy_from_slice(&hash[12..]);
299 Address::from(bytes)
300}
301
302pub fn get_create2_address(
307 from: impl Into<Address>,
308 salt: impl AsRef<[u8]>,
309 init_code: impl AsRef<[u8]>,
310) -> Address {
311 let init_code_hash = keccak256(init_code.as_ref());
312 get_create2_address_from_hash(from, salt, init_code_hash)
313}
314
315pub fn get_create2_address_from_hash(
364 from: impl Into<Address>,
365 salt: impl AsRef<[u8]>,
366 init_code_hash: impl AsRef<[u8]>,
367) -> Address {
368 let from = from.into();
369 let salt = salt.as_ref();
370 let init_code_hash = init_code_hash.as_ref();
371
372 let mut bytes = Vec::with_capacity(1 + 20 + salt.len() + init_code_hash.len());
373 bytes.push(0xff);
374 bytes.extend_from_slice(from.as_bytes());
375 bytes.extend_from_slice(salt);
376 bytes.extend_from_slice(init_code_hash);
377
378 let hash = keccak256(bytes);
379
380 let mut bytes = [0u8; 20];
381 bytes.copy_from_slice(&hash[12..]);
382 Address::from(bytes)
383}
384
385pub fn secret_key_to_address(secret_key: &SigningKey) -> Address {
387 let public_key = K256PublicKey::from(&secret_key.verifying_key());
388 let public_key = public_key.to_encoded_point(false);
389 let public_key = public_key.as_bytes();
390 debug_assert_eq!(public_key[0], 0x04);
391 let hash = keccak256(&public_key[1..]);
392
393 let mut bytes = [0u8; 20];
394 bytes.copy_from_slice(&hash[12..]);
395 Address::from(bytes)
396}
397
398pub fn to_checksum(addr: &Address, chain_id: Option<u8>) -> String {
407 let prefixed_addr = match chain_id {
408 Some(chain_id) => format!("{chain_id}0x{addr:x}"),
409 None => format!("{addr:x}"),
410 };
411 let hash = hex::encode(keccak256(prefixed_addr));
412 let hash = hash.as_bytes();
413
414 let addr_hex = hex::encode(addr.as_bytes());
415 let addr_hex = addr_hex.as_bytes();
416
417 addr_hex.iter().zip(hash).fold("0x".to_owned(), |mut encoded, (addr, hash)| {
418 encoded.push(if *hash >= 56 {
419 addr.to_ascii_uppercase() as char
420 } else {
421 addr.to_ascii_lowercase() as char
422 });
423 encoded
424 })
425}
426
427pub fn format_bytes32_string(text: &str) -> Result<[u8; 32], ConversionError> {
430 let str_bytes: &[u8] = text.as_bytes();
431 if str_bytes.len() > 32 {
432 return Err(ConversionError::TextTooLong)
433 }
434
435 let mut bytes32: [u8; 32] = [0u8; 32];
436 bytes32[..str_bytes.len()].copy_from_slice(str_bytes);
437
438 Ok(bytes32)
439}
440
441pub fn parse_bytes32_string(bytes: &[u8; 32]) -> Result<&str, ConversionError> {
443 let mut length = 0;
444 while length < 32 && bytes[length] != 0 {
445 length += 1;
446 }
447
448 Ok(std::str::from_utf8(&bytes[..length])?)
449}
450
451pub fn eip1559_default_estimator(base_fee_per_gas: U256, rewards: Vec<Vec<U256>>) -> (U256, U256) {
453 let max_priority_fee_per_gas =
454 if base_fee_per_gas < U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) {
455 U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE)
456 } else {
457 std::cmp::max(
458 estimate_priority_fee(rewards),
459 U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE),
460 )
461 };
462 let potential_max_fee = base_fee_surged(base_fee_per_gas);
463 let max_fee_per_gas = if max_priority_fee_per_gas > potential_max_fee {
464 max_priority_fee_per_gas + potential_max_fee
465 } else {
466 potential_max_fee
467 };
468 (max_fee_per_gas, max_priority_fee_per_gas)
469}
470
471pub fn from_int_or_hex<'de, D>(deserializer: D) -> Result<U256, D::Error>
474where
475 D: Deserializer<'de>,
476{
477 #[derive(Deserialize)]
478 #[serde(untagged)]
479 enum IntOrHex {
480 Int(serde_json::Number),
481 Hex(String),
482 }
483
484 match IntOrHex::deserialize(deserializer)? {
485 IntOrHex::Hex(s) => U256::from_str(s.as_str()).map_err(serde::de::Error::custom),
486 IntOrHex::Int(n) => U256::from_dec_str(&n.to_string()).map_err(serde::de::Error::custom),
487 }
488}
489
490pub fn from_u64_or_hex<'de, D>(deserializer: D) -> Result<U64, D::Error>
493where
494 D: Deserializer<'de>,
495{
496 #[derive(Deserialize)]
497 #[serde(untagged)]
498 enum IntOrHex {
499 Int(serde_json::Number),
500 Hex(String),
501 }
502
503 match IntOrHex::deserialize(deserializer)? {
504 IntOrHex::Hex(s) => U64::from_str(s.as_str()).map_err(serde::de::Error::custom),
505 IntOrHex::Int(n) => U64::from_dec_str(&n.to_string()).map_err(serde::de::Error::custom),
506 }
507}
508
509pub fn from_int_or_hex_opt<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
512where
513 D: Deserializer<'de>,
514{
515 Ok(Some(from_int_or_hex(deserializer)?))
516}
517
518pub fn from_u64_or_hex_opt<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
521where
522 D: Deserializer<'de>,
523{
524 Ok(Some(from_u64_or_hex(deserializer)?.as_u64()))
525}
526
527fn estimate_priority_fee(rewards: Vec<Vec<U256>>) -> U256 {
528 let mut rewards: Vec<U256> =
529 rewards.iter().map(|r| r[0]).filter(|r| *r > U256::zero()).collect();
530 if rewards.is_empty() {
531 return U256::zero()
532 }
533 if rewards.len() == 1 {
534 return rewards[0]
535 }
536 rewards.sort();
538
539 let mut rewards_copy = rewards.clone();
542 rewards_copy.rotate_left(1);
543
544 let mut percentage_change: Vec<I256> = rewards
545 .iter()
546 .zip(rewards_copy.iter())
547 .map(|(a, b)| {
548 let a = I256::try_from(*a).expect("priority fee overflow");
549 let b = I256::try_from(*b).expect("priority fee overflow");
550 ((b - a) * 100) / a
551 })
552 .collect();
553 percentage_change.pop();
554
555 let max_change = percentage_change.iter().max().unwrap();
557 let max_change_index = percentage_change.iter().position(|&c| c == *max_change).unwrap();
558
559 let values = if *max_change >= EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE.into() &&
562 (max_change_index >= (rewards.len() / 2))
563 {
564 rewards[max_change_index..].to_vec()
565 } else {
566 rewards
567 };
568
569 values[values.len() / 2]
571}
572
573fn base_fee_surged(base_fee_per_gas: U256) -> U256 {
574 if base_fee_per_gas <= U256::from(40_000_000_000u64) {
575 base_fee_per_gas * 2
576 } else if base_fee_per_gas <= U256::from(100_000_000_000u64) {
577 base_fee_per_gas * 16 / 10
578 } else if base_fee_per_gas <= U256::from(200_000_000_000u64) {
579 base_fee_per_gas * 14 / 10
580 } else {
581 base_fee_per_gas * 12 / 10
582 }
583}
584
585#[cfg(not(target_arch = "wasm32"))]
590pub(crate) fn unused_port() -> u16 {
591 let listener = std::net::TcpListener::bind("127.0.0.1:0")
592 .expect("Failed to create TCP listener to find unused port");
593
594 let local_addr =
595 listener.local_addr().expect("Failed to read TCP listener local_addr to find unused port");
596 local_addr.port()
597}
598
599#[cfg(test)]
600mod tests {
601 use super::*;
602 use hex_literal::hex;
603
604 #[test]
605 fn wei_in_ether() {
606 assert_eq!(WEI_IN_ETHER.as_u64(), 1e18 as u64);
607 }
608
609 #[test]
610 fn test_format_units_unsigned() {
611 let gwei_in_ether = format_units(WEI_IN_ETHER, 9).unwrap();
612 assert_eq!(gwei_in_ether.parse::<f64>().unwrap() as u64, 1e9 as u64);
613
614 let eth = format_units(WEI_IN_ETHER, "ether").unwrap();
615 assert_eq!(eth.parse::<f64>().unwrap() as u64, 1);
616
617 let eth = format_units(1395633240123456000_u128, "ether").unwrap();
618 assert_eq!(eth.parse::<f64>().unwrap(), 1.395633240123456);
619
620 let eth =
621 format_units(U256::from_dec_str("1395633240123456000").unwrap(), "ether").unwrap();
622 assert_eq!(eth.parse::<f64>().unwrap(), 1.395633240123456);
623
624 let eth =
625 format_units(U256::from_dec_str("1395633240123456789").unwrap(), "ether").unwrap();
626 assert_eq!(eth, "1.395633240123456789");
627
628 let eth =
629 format_units(U256::from_dec_str("1005633240123456789").unwrap(), "ether").unwrap();
630 assert_eq!(eth, "1.005633240123456789");
631
632 let eth = format_units(u8::MAX, 4).unwrap();
633 assert_eq!(eth, "0.0255");
634
635 let eth = format_units(u16::MAX, "ether").unwrap();
636 assert_eq!(eth, "0.000000000000065535");
637
638 let eth = format_units(u32::MAX, 18).unwrap();
640 assert_eq!(eth, "0.000000004294967295");
641
642 let eth = format_units(u64::MAX, "gwei").unwrap();
644 assert_eq!(eth, "18446744073.709551615");
645
646 let eth = format_units(u128::MAX, 36).unwrap();
647 assert_eq!(eth, "340.282366920938463463374607431768211455");
648
649 let eth = format_units(U256::MAX, 77).unwrap();
650 assert_eq!(
651 eth,
652 "1.15792089237316195423570985008687907853269984665640564039457584007913129639935"
653 );
654
655 let err = format_units(U256::MAX, 78).unwrap_err();
656 assert!(matches!(err, ConversionError::ParseOverflow));
657 }
658
659 #[test]
660 fn test_format_units_signed() {
661 let eth =
662 format_units(I256::from_dec_str("-1395633240123456000").unwrap(), "ether").unwrap();
663 assert_eq!(eth.parse::<f64>().unwrap(), -1.395633240123456);
664
665 let eth =
666 format_units(I256::from_dec_str("-1395633240123456789").unwrap(), "ether").unwrap();
667 assert_eq!(eth, "-1.395633240123456789");
668
669 let eth =
670 format_units(I256::from_dec_str("1005633240123456789").unwrap(), "ether").unwrap();
671 assert_eq!(eth, "1.005633240123456789");
672
673 let eth = format_units(i8::MIN, 4).unwrap();
674 assert_eq!(eth, "-0.0128");
675 assert_eq!(eth.parse::<f64>().unwrap(), -0.0128_f64);
676
677 let eth = format_units(i8::MAX, 4).unwrap();
678 assert_eq!(eth, "0.0127");
679 assert_eq!(eth.parse::<f64>().unwrap(), 0.0127);
680
681 let eth = format_units(i16::MIN, "ether").unwrap();
682 assert_eq!(eth, "-0.000000000000032768");
683
684 let eth = format_units(i32::MIN, 18).unwrap();
686 assert_eq!(eth, "-0.000000002147483648");
687
688 let eth = format_units(i64::MIN, "gwei").unwrap();
690 assert_eq!(eth, "-9223372036.854775808");
691
692 let eth = format_units(i128::MIN, 36).unwrap();
693 assert_eq!(eth, "-170.141183460469231731687303715884105728");
694
695 let eth = format_units(I256::MIN, 76).unwrap();
696 assert_eq!(
697 eth,
698 "-5.7896044618658097711785492504343953926634992332820282019728792003956564819968"
699 );
700
701 let err = format_units(I256::MIN, 77).unwrap_err();
702 assert!(matches!(err, ConversionError::ParseOverflow));
703 }
704
705 #[test]
706 fn parse_large_units() {
707 let decimals = 27u32;
708 let val = "10.55";
709
710 let n: U256 = parse_units(val, decimals).unwrap().into();
711 assert_eq!(n.to_string(), "10550000000000000000000000000");
712 }
713
714 #[test]
715 fn test_parse_units() {
716 let gwei: U256 = parse_units(1.5, 9).unwrap().into();
717 assert_eq!(gwei.as_u64(), 15e8 as u64);
718
719 let token: U256 = parse_units(1163.56926418, 8).unwrap().into();
720 assert_eq!(token.as_u64(), 116356926418);
721
722 let eth_dec_float: U256 = parse_units(1.39563324, "ether").unwrap().into();
723 assert_eq!(eth_dec_float, U256::from_dec_str("1395633240000000000").unwrap());
724
725 let eth_dec_string: U256 = parse_units("1.39563324", "ether").unwrap().into();
726 assert_eq!(eth_dec_string, U256::from_dec_str("1395633240000000000").unwrap());
727
728 let eth: U256 = parse_units(1, "ether").unwrap().into();
729 assert_eq!(eth, WEI_IN_ETHER);
730
731 let val: U256 = parse_units("2.3", "ether").unwrap().into();
732 assert_eq!(val, U256::from_dec_str("2300000000000000000").unwrap());
733
734 let n: U256 = parse_units(".2", 2).unwrap().into();
735 assert_eq!(n, U256::from(20), "leading dot");
736
737 let n: U256 = parse_units("333.21", 2).unwrap().into();
738 assert_eq!(n, U256::from(33321), "trailing dot");
739
740 let n: U256 = parse_units("98766", 16).unwrap().into();
741 assert_eq!(n, U256::from_dec_str("987660000000000000000").unwrap(), "no dot");
742
743 let n: U256 = parse_units("3_3_0", 3).unwrap().into();
744 assert_eq!(n, U256::from(330000), "underscore");
745
746 let n: U256 = parse_units("330", 0).unwrap().into();
747 assert_eq!(n, U256::from(330), "zero decimals");
748
749 let n: U256 = parse_units(".1234", 3).unwrap().into();
750 assert_eq!(n, U256::from(123), "truncate too many decimals");
751
752 assert!(parse_units("1", 80).is_err(), "overflow");
753 assert!(parse_units("1", -1).is_err(), "neg units");
754
755 let two_e30 = U256::from(2) * U256([0x4674edea40000000, 0xc9f2c9cd0, 0x0, 0x0]);
756 let n: U256 = parse_units("2", 30).unwrap().into();
757 assert_eq!(n, two_e30, "2e30");
758
759 let n: U256 = parse_units(".33_319_2", 0).unwrap().into();
760 assert_eq!(n, U256::zero(), "mix");
761
762 let n: U256 = parse_units("", 3).unwrap().into();
763 assert_eq!(n, U256::zero(), "empty");
764 }
765
766 #[test]
767 fn test_signed_parse_units() {
768 let gwei: I256 = parse_units(-1.5, 9).unwrap().into();
769 assert_eq!(gwei.as_i64(), -15e8 as i64);
770
771 let token: I256 = parse_units(-1163.56926418, 8).unwrap().into();
772 assert_eq!(token.as_i64(), -116356926418);
773
774 let eth_dec_float: I256 = parse_units(-1.39563324, "ether").unwrap().into();
775 assert_eq!(eth_dec_float, I256::from_dec_str("-1395633240000000000").unwrap());
776
777 let eth_dec_string: I256 = parse_units("-1.39563324", "ether").unwrap().into();
778 assert_eq!(eth_dec_string, I256::from_dec_str("-1395633240000000000").unwrap());
779
780 let eth: I256 = parse_units(-1, "ether").unwrap().into();
781 assert_eq!(eth, I256::from_raw(WEI_IN_ETHER) * I256::minus_one());
782
783 let val: I256 = parse_units("-2.3", "ether").unwrap().into();
784 assert_eq!(val, I256::from_dec_str("-2300000000000000000").unwrap());
785
786 let n: I256 = parse_units("-.2", 2).unwrap().into();
787 assert_eq!(n, I256::from(-20), "leading dot");
788
789 let n: I256 = parse_units("-333.21", 2).unwrap().into();
790 assert_eq!(n, I256::from(-33321), "trailing dot");
791
792 let n: I256 = parse_units("-98766", 16).unwrap().into();
793 assert_eq!(n, I256::from_dec_str("-987660000000000000000").unwrap(), "no dot");
794
795 let n: I256 = parse_units("-3_3_0", 3).unwrap().into();
796 assert_eq!(n, I256::from(-330000), "underscore");
797
798 let n: I256 = parse_units("-330", 0).unwrap().into();
799 assert_eq!(n, I256::from(-330), "zero decimals");
800
801 let n: I256 = parse_units("-.1234", 3).unwrap().into();
802 assert_eq!(n, I256::from(-123), "truncate too many decimals");
803
804 assert!(parse_units("-1", 80).is_err(), "overflow");
805
806 let two_e30 =
807 I256::from(-2) * I256::from_raw(U256([0x4674edea40000000, 0xc9f2c9cd0, 0x0, 0x0]));
808 let n: I256 = parse_units("-2", 30).unwrap().into();
809 assert_eq!(n, two_e30, "-2e30");
810
811 let n: I256 = parse_units("-.33_319_2", 0).unwrap().into();
812 assert_eq!(n, I256::zero(), "mix");
813
814 let n: I256 = parse_units("-", 3).unwrap().into();
815 assert_eq!(n, I256::zero(), "empty");
816 }
817
818 #[test]
819 fn addr_checksum() {
820 let addr_list = vec![
821 (
823 None,
824 "27b1fdb04752bbc536007a920d24acb045561c26",
825 "0x27b1fdb04752bbc536007a920d24acb045561c26",
826 ),
827 (
828 None,
829 "3599689e6292b81b2d85451025146515070129bb",
830 "0x3599689E6292b81B2d85451025146515070129Bb",
831 ),
832 (
833 None,
834 "42712d45473476b98452f434e72461577d686318",
835 "0x42712D45473476b98452f434e72461577D686318",
836 ),
837 (
838 None,
839 "52908400098527886e0f7030069857d2e4169ee7",
840 "0x52908400098527886E0F7030069857D2E4169EE7",
841 ),
842 (
843 None,
844 "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed",
845 "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
846 ),
847 (
848 None,
849 "6549f4939460de12611948b3f82b88c3c8975323",
850 "0x6549f4939460DE12611948b3f82b88C3C8975323",
851 ),
852 (
853 None,
854 "66f9664f97f2b50f62d13ea064982f936de76657",
855 "0x66f9664f97F2b50F62D13eA064982f936dE76657",
856 ),
857 (
858 None,
859 "88021160c5c792225e4e5452585947470010289d",
860 "0x88021160C5C792225E4E5452585947470010289D",
861 ),
862 (
864 Some(30),
865 "27b1fdb04752bbc536007a920d24acb045561c26",
866 "0x27b1FdB04752BBc536007A920D24ACB045561c26",
867 ),
868 (
869 Some(30),
870 "3599689e6292b81b2d85451025146515070129bb",
871 "0x3599689E6292B81B2D85451025146515070129Bb",
872 ),
873 (
874 Some(30),
875 "42712d45473476b98452f434e72461577d686318",
876 "0x42712D45473476B98452f434E72461577d686318",
877 ),
878 (
879 Some(30),
880 "52908400098527886e0f7030069857d2e4169ee7",
881 "0x52908400098527886E0F7030069857D2E4169ee7",
882 ),
883 (
884 Some(30),
885 "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed",
886 "0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD",
887 ),
888 (
889 Some(30),
890 "6549f4939460de12611948b3f82b88c3c8975323",
891 "0x6549F4939460DE12611948B3F82B88C3C8975323",
892 ),
893 (
894 Some(30),
895 "66f9664f97f2b50f62d13ea064982f936de76657",
896 "0x66F9664f97f2B50F62d13EA064982F936de76657",
897 ),
898 ];
899
900 for (chain_id, addr, checksummed_addr) in addr_list {
901 let addr = addr.parse::<Address>().unwrap();
902 assert_eq!(to_checksum(&addr, chain_id), String::from(checksummed_addr));
903 }
904 }
905
906 #[test]
907 fn contract_address() {
908 let from = "6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0".parse::<Address>().unwrap();
910 for (nonce, expected) in [
911 "cd234a471b72ba2f1ccf0a70fcaba648a5eecd8d",
912 "343c43a37d37dff08ae8c4a11544c718abb4fcf8",
913 "f778b86fa74e846c4f0a1fbd1335fe81c00a0c91",
914 "fffd933a0bc612844eaf0c6fe3e5b8e9b6c1d19c",
915 ]
916 .iter()
917 .enumerate()
918 {
919 let address = get_contract_address(from, nonce);
920 assert_eq!(address, expected.parse::<Address>().unwrap());
921 }
922 }
923
924 #[test]
925 fn create2_address() {
927 for (from, salt, init_code, expected) in &[
928 (
929 "0000000000000000000000000000000000000000",
930 "0000000000000000000000000000000000000000000000000000000000000000",
931 "00",
932 "4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38",
933 ),
934 (
935 "deadbeef00000000000000000000000000000000",
936 "0000000000000000000000000000000000000000000000000000000000000000",
937 "00",
938 "B928f69Bb1D91Cd65274e3c79d8986362984fDA3",
939 ),
940 (
941 "deadbeef00000000000000000000000000000000",
942 "000000000000000000000000feed000000000000000000000000000000000000",
943 "00",
944 "D04116cDd17beBE565EB2422F2497E06cC1C9833",
945 ),
946 (
947 "0000000000000000000000000000000000000000",
948 "0000000000000000000000000000000000000000000000000000000000000000",
949 "deadbeef",
950 "70f2b2914A2a4b783FaEFb75f459A580616Fcb5e",
951 ),
952 (
953 "00000000000000000000000000000000deadbeef",
954 "00000000000000000000000000000000000000000000000000000000cafebabe",
955 "deadbeef",
956 "60f3f640a8508fC6a86d45DF051962668E1e8AC7",
957 ),
958 (
959 "00000000000000000000000000000000deadbeef",
960 "00000000000000000000000000000000000000000000000000000000cafebabe",
961 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
962 "1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C",
963 ),
964 (
965 "0000000000000000000000000000000000000000",
966 "0000000000000000000000000000000000000000000000000000000000000000",
967 "",
968 "E33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0",
969 ),
970 ] {
971 let from = from.parse::<Address>().unwrap();
973 let salt = hex::decode(salt).unwrap();
974 let init_code = hex::decode(init_code).unwrap();
975 let expected = expected.parse::<Address>().unwrap();
976 assert_eq!(expected, get_create2_address(from, salt.clone(), init_code.clone()));
977
978 let init_code_hash = keccak256(init_code).to_vec();
980 assert_eq!(expected, get_create2_address_from_hash(from, salt, init_code_hash))
981 }
982 }
983
984 #[test]
985 fn bytes32_string_parsing() {
986 let text_bytes_list = vec![
987 ("", hex!("0000000000000000000000000000000000000000000000000000000000000000")),
988 ("A", hex!("4100000000000000000000000000000000000000000000000000000000000000")),
989 (
990 "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
991 hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a303132333435"),
992 ),
993 (
994 "!@#$%^&*(),./;'[]",
995 hex!("21402324255e262a28292c2e2f3b275b5d000000000000000000000000000000"),
996 ),
997 ];
998
999 for (text, bytes) in text_bytes_list {
1000 assert_eq!(text, parse_bytes32_string(&bytes).unwrap());
1001 }
1002 }
1003
1004 #[test]
1005 fn bytes32_string_formatting() {
1006 let text_bytes_list = vec![
1007 ("", hex!("0000000000000000000000000000000000000000000000000000000000000000")),
1008 ("A", hex!("4100000000000000000000000000000000000000000000000000000000000000")),
1009 (
1010 "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
1011 hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a303132333435"),
1012 ),
1013 (
1014 "!@#$%^&*(),./;'[]",
1015 hex!("21402324255e262a28292c2e2f3b275b5d000000000000000000000000000000"),
1016 ),
1017 ];
1018
1019 for (text, bytes) in text_bytes_list {
1020 assert_eq!(bytes, format_bytes32_string(text).unwrap());
1021 }
1022 }
1023
1024 #[test]
1025 fn bytes32_string_formatting_too_long() {
1026 assert!(matches!(
1027 format_bytes32_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456").unwrap_err(),
1028 ConversionError::TextTooLong
1029 ));
1030 }
1031
1032 #[test]
1033 fn test_eip1559_default_estimator() {
1034 let base_fee_per_gas = U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) - 1;
1037 let rewards: Vec<Vec<U256>> = vec![vec![]];
1038 let (base_fee, priority_fee) = eip1559_default_estimator(base_fee_per_gas, rewards);
1039 assert_eq!(priority_fee, U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE));
1040 assert_eq!(base_fee, base_fee_surged(base_fee_per_gas));
1041
1042 let base_fee_per_gas = U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) + 1;
1045 let rewards: Vec<Vec<U256>> = vec![
1046 vec![100_000_000_000u64.into()],
1047 vec![105_000_000_000u64.into()],
1048 vec![102_000_000_000u64.into()],
1049 ]; let (base_fee, priority_fee) = eip1559_default_estimator(base_fee_per_gas, rewards.clone());
1051 assert_eq!(base_fee, base_fee_surged(base_fee_per_gas));
1052 assert_eq!(priority_fee, estimate_priority_fee(rewards.clone()));
1053
1054 assert_eq!(estimate_priority_fee(rewards), 102_000_000_000u64.into());
1056
1057 let overflow = U256::from(u32::MAX) + 1;
1060 let rewards_overflow: Vec<Vec<U256>> = vec![vec![overflow], vec![overflow]];
1061 assert_eq!(estimate_priority_fee(rewards_overflow), overflow);
1062 }
1063}