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, Bytes, ParseI256Error, H256, I256, U256};
40use elliptic_curve::sec1::ToEncodedPoint;
41use ethabi::ethereum_types::FromDecStrErr;
42use k256::{
43 ecdsa::{SigningKey, VerifyingKey},
44 AffinePoint,
45};
46use std::{collections::HashMap, fmt};
47use thiserror::Error;
48
49const OVERFLOW_I256_UNITS: usize = 77;
51const OVERFLOW_U256_UNITS: usize = 78;
53
54#[doc(hidden)]
56pub use serde_json as __serde_json;
57
58#[derive(Error, Debug)]
59pub enum ConversionError {
60 #[error("Unknown units: {0}")]
61 UnrecognizedUnits(String),
62 #[error("bytes32 strings must not exceed 32 bytes in length")]
63 TextTooLong,
64 #[error(transparent)]
65 Utf8Error(#[from] std::str::Utf8Error),
66 #[error(transparent)]
67 InvalidFloat(#[from] std::num::ParseFloatError),
68 #[error(transparent)]
69 FromDecStrError(#[from] FromDecStrErr),
70 #[error("Overflow parsing string")]
71 ParseOverflow,
72 #[error(transparent)]
73 ParseI256Error(#[from] ParseI256Error),
74 #[error("Invalid address checksum")]
75 InvalidAddressChecksum,
76 #[error(transparent)]
77 FromHexError(<Address as std::str::FromStr>::Err),
78}
79
80pub const WEI_IN_ETHER: U256 = U256([0x0de0b6b3a7640000, 0x0, 0x0, 0x0]);
82
83pub const EIP1559_FEE_ESTIMATION_PAST_BLOCKS: u64 = 10;
85pub const EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE: f64 = 5.0;
87pub const EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE: u64 = 3_000_000_000;
89pub const EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER: u64 = 100_000_000_000;
92pub const EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE: i64 = 200;
95
96#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
99pub enum ParseUnits {
100 U256(U256),
101 I256(I256),
102}
103
104impl From<ParseUnits> for U256 {
105 fn from(n: ParseUnits) -> Self {
106 match n {
107 ParseUnits::U256(n) => n,
108 ParseUnits::I256(n) => n.into_raw(),
109 }
110 }
111}
112
113impl fmt::Display for ParseUnits {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 ParseUnits::U256(val) => val.fmt(f),
117 ParseUnits::I256(val) => val.fmt(f),
118 }
119 }
120}
121
122macro_rules! construct_format_units_from {
123 ($( $t:ty[$convert:ident] ),*) => {
124 $(
125 impl From<$t> for ParseUnits {
126 fn from(num: $t) -> Self {
127 Self::$convert(num.into())
128 }
129 }
130 )*
131 }
132}
133
134construct_format_units_from! {
136 u8[U256], u16[U256], u32[U256], u64[U256], u128[U256], U256[U256], usize[U256],
137 i8[I256], i16[I256], i32[I256], i64[I256], i128[I256], I256[I256], isize[I256]
138}
139
140pub fn format_ether<T: Into<ParseUnits>>(amount: T) -> String {
151 format_units(amount, "ether").unwrap()
153}
154
155pub fn format_units<T, K>(amount: T, units: K) -> Result<String, ConversionError>
176where
177 T: Into<ParseUnits>,
178 K: TryInto<Units, Error = ConversionError>,
179{
180 let units: usize = units.try_into()?.into();
181 let amount = amount.into();
182
183 match amount {
184 ParseUnits::U256(_) if units >= OVERFLOW_U256_UNITS => {
186 return Err(ConversionError::ParseOverflow)
187 }
188 ParseUnits::I256(_) if units >= OVERFLOW_I256_UNITS => {
190 return Err(ConversionError::ParseOverflow)
191 }
192 _ => {}
193 };
194 let exp10 = U256::exp10(units);
195
196 match amount {
198 ParseUnits::U256(amount) => {
199 let integer = amount / exp10;
200 let decimals = (amount % exp10).to_string();
201 Ok(format!("{integer}.{decimals:0>units$}"))
202 }
203 ParseUnits::I256(amount) => {
204 let exp10 = I256::from_raw(exp10);
205 let sign = if amount.is_negative() { "-" } else { "" };
206 let integer = (amount / exp10).twos_complement();
207 let decimals = ((amount % exp10).twos_complement()).to_string();
208 Ok(format!("{sign}{integer}.{decimals:0>units$}"))
209 }
210 }
211}
212
213pub fn parse_ether<S: ToString>(eth: S) -> Result<U256, ConversionError> {
224 Ok(parse_units(eth, "ether")?.into())
225}
226
227pub fn parse_units<K, S>(amount: S, units: K) -> Result<ParseUnits, ConversionError>
246where
247 S: ToString,
248 K: TryInto<Units, Error = ConversionError> + Copy,
249{
250 let exponent: u32 = units.try_into()?.as_num();
251 let mut amount_str = amount.to_string().replace('_', "");
252 let negative = amount_str.chars().next().unwrap_or_default() == '-';
253 let dec_len = if let Some(di) = amount_str.find('.') {
254 amount_str.remove(di);
255 amount_str[di..].len() as u32
256 } else {
257 0
258 };
259
260 if dec_len > exponent {
261 let amount_str = &amount_str[..(amount_str.len() - (dec_len - exponent) as usize)];
263 if negative {
264 if amount_str == "-" {
267 Ok(ParseUnits::I256(I256::zero()))
268 } else {
269 Ok(ParseUnits::I256(I256::from_dec_str(amount_str)?))
270 }
271 } else {
272 Ok(ParseUnits::U256(U256::from_dec_str(amount_str)?))
273 }
274 } else if negative {
275 if amount_str == "-" {
277 Ok(ParseUnits::I256(I256::zero()))
278 } else {
279 let mut n = I256::from_dec_str(&amount_str)?;
280 n *= I256::from(10)
281 .checked_pow(exponent - dec_len)
282 .ok_or(ConversionError::ParseOverflow)?;
283 Ok(ParseUnits::I256(n))
284 }
285 } else {
286 let mut a_uint = U256::from_dec_str(&amount_str)?;
287 a_uint *= U256::from(10)
288 .checked_pow(U256::from(exponent - dec_len))
289 .ok_or(ConversionError::ParseOverflow)?;
290 Ok(ParseUnits::U256(a_uint))
291 }
292}
293
294pub fn get_contract_address(sender: impl Into<Address>, nonce: impl Into<U256>) -> Address {
298 let mut stream = rlp::RlpStream::new();
299 stream.begin_list(2);
300 stream.append(&sender.into());
301 stream.append(&nonce.into());
302
303 let hash = keccak256(&stream.out());
304
305 let mut bytes = [0u8; 20];
306 bytes.copy_from_slice(&hash[12..]);
307 Address::from(bytes)
308}
309
310pub fn get_create2_address(
315 from: impl Into<Address>,
316 salt: impl AsRef<[u8]>,
317 init_code: impl AsRef<[u8]>,
318) -> Address {
319 let init_code_hash = keccak256(init_code.as_ref());
320 get_create2_address_from_hash(from, salt, init_code_hash)
321}
322
323pub fn get_create2_address_from_hash(
372 from: impl Into<Address>,
373 salt: impl AsRef<[u8]>,
374 init_code_hash: impl AsRef<[u8]>,
375) -> Address {
376 let from = from.into();
377 let salt = salt.as_ref();
378 let init_code_hash = init_code_hash.as_ref();
379
380 let mut bytes = Vec::with_capacity(1 + 20 + salt.len() + init_code_hash.len());
381 bytes.push(0xff);
382 bytes.extend_from_slice(from.as_bytes());
383 bytes.extend_from_slice(salt);
384 bytes.extend_from_slice(init_code_hash);
385
386 let hash = keccak256(bytes);
387
388 let mut bytes = [0u8; 20];
389 bytes.copy_from_slice(&hash[12..]);
390 Address::from(bytes)
391}
392
393pub fn raw_public_key_to_address<T: AsRef<[u8]>>(pubkey: T) -> Address {
405 let pubkey = pubkey.as_ref();
406 assert_eq!(pubkey.len(), 64, "raw public key must be 64 bytes");
407 let digest = keccak256(pubkey);
408 Address::from_slice(&digest[12..])
409}
410
411pub fn public_key_to_address(pubkey: &VerifyingKey) -> Address {
414 let affine: &AffinePoint = pubkey.as_ref();
415 let encoded = affine.to_encoded_point(false);
416 raw_public_key_to_address(&encoded.as_bytes()[1..])
417}
418
419pub fn secret_key_to_address(secret_key: &SigningKey) -> Address {
421 let public_key = secret_key.verifying_key();
422
423 public_key_to_address(public_key)
424}
425
426pub fn to_checksum(addr: &Address, chain_id: Option<u8>) -> String {
435 let prefixed_addr = match chain_id {
436 Some(chain_id) => format!("{chain_id}0x{addr:x}"),
437 None => format!("{addr:x}"),
438 };
439 let hash = hex::encode(keccak256(prefixed_addr));
440 let hash = hash.as_bytes();
441
442 let addr_hex = hex::encode(addr.as_bytes());
443 let addr_hex = addr_hex.as_bytes();
444
445 addr_hex.iter().zip(hash).fold("0x".to_owned(), |mut encoded, (addr, hash)| {
446 encoded.push(if *hash >= 56 {
447 addr.to_ascii_uppercase() as char
448 } else {
449 addr.to_ascii_lowercase() as char
450 });
451 encoded
452 })
453}
454
455pub fn parse_checksummed(addr: &str, chain_id: Option<u8>) -> Result<Address, ConversionError> {
460 let addr = addr.strip_prefix("0x").unwrap_or(addr);
461 let address: Address = addr.parse().map_err(ConversionError::FromHexError)?;
462 let checksum_addr = to_checksum(&address, chain_id);
463
464 if checksum_addr.strip_prefix("0x").unwrap_or(&checksum_addr) == addr {
465 Ok(address)
466 } else {
467 Err(ConversionError::InvalidAddressChecksum)
468 }
469}
470
471pub fn format_bytes32_string(text: &str) -> Result<[u8; 32], ConversionError> {
474 let str_bytes: &[u8] = text.as_bytes();
475 if str_bytes.len() > 32 {
476 return Err(ConversionError::TextTooLong)
477 }
478
479 let mut bytes32: [u8; 32] = [0u8; 32];
480 bytes32[..str_bytes.len()].copy_from_slice(str_bytes);
481
482 Ok(bytes32)
483}
484
485pub fn parse_bytes32_string(bytes: &[u8; 32]) -> Result<&str, ConversionError> {
487 let mut length = 0;
488 while length < 32 && bytes[length] != 0 {
489 length += 1;
490 }
491
492 Ok(std::str::from_utf8(&bytes[..length])?)
493}
494
495pub fn eip1559_default_estimator(base_fee_per_gas: U256, rewards: Vec<Vec<U256>>) -> (U256, U256) {
497 let max_priority_fee_per_gas =
498 if base_fee_per_gas < U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) {
499 U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE)
500 } else {
501 std::cmp::max(
502 estimate_priority_fee(rewards),
503 U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE),
504 )
505 };
506 let potential_max_fee = base_fee_surged(base_fee_per_gas);
507 let max_fee_per_gas = if max_priority_fee_per_gas > potential_max_fee {
508 max_priority_fee_per_gas + potential_max_fee
509 } else {
510 potential_max_fee
511 };
512 (max_fee_per_gas, max_priority_fee_per_gas)
513}
514
515pub fn from_bytes_to_h256<'de, D>(bytes: Bytes) -> Result<H256, D::Error>
518where
519 D: Deserializer<'de>,
520{
521 if bytes.0.len() > 32 {
522 return Err(serde::de::Error::custom("input too long to be a H256"))
523 }
524
525 let mut padded = [0u8; 32];
527 padded[32 - bytes.0.len()..].copy_from_slice(&bytes.0);
528
529 Ok(H256::from_slice(&padded))
531}
532
533pub fn from_unformatted_hex_map<'de, D>(
536 deserializer: D,
537) -> Result<Option<HashMap<H256, H256>>, D::Error>
538where
539 D: Deserializer<'de>,
540{
541 let map = Option::<HashMap<Bytes, Bytes>>::deserialize(deserializer)?;
542 match map {
543 Some(mut map) => {
544 let mut res_map = HashMap::new();
545 for (k, v) in map.drain() {
546 let k_deserialized = from_bytes_to_h256::<'de, D>(k)?;
547 let v_deserialized = from_bytes_to_h256::<'de, D>(v)?;
548 res_map.insert(k_deserialized, v_deserialized);
549 }
550 Ok(Some(res_map))
551 }
552 None => Ok(None),
553 }
554}
555
556fn estimate_priority_fee(rewards: Vec<Vec<U256>>) -> U256 {
557 let mut rewards: Vec<U256> =
558 rewards.iter().map(|r| r[0]).filter(|r| *r > U256::zero()).collect();
559 if rewards.is_empty() {
560 return U256::zero()
561 }
562 if rewards.len() == 1 {
563 return rewards[0]
564 }
565 rewards.sort();
567
568 let mut rewards_copy = rewards.clone();
571 rewards_copy.rotate_left(1);
572
573 let mut percentage_change: Vec<I256> = rewards
574 .iter()
575 .zip(rewards_copy.iter())
576 .map(|(a, b)| {
577 let a = I256::try_from(*a).expect("priority fee overflow");
578 let b = I256::try_from(*b).expect("priority fee overflow");
579 ((b - a) * 100) / a
580 })
581 .collect();
582 percentage_change.pop();
583
584 let max_change = percentage_change.iter().max().unwrap();
586 let max_change_index = percentage_change.iter().position(|&c| c == *max_change).unwrap();
587
588 let values = if *max_change >= EIP1559_FEE_ESTIMATION_THRESHOLD_MAX_CHANGE.into() &&
591 (max_change_index >= (rewards.len() / 2))
592 {
593 rewards[max_change_index..].to_vec()
594 } else {
595 rewards
596 };
597
598 values[values.len() / 2]
600}
601
602fn base_fee_surged(base_fee_per_gas: U256) -> U256 {
603 if base_fee_per_gas <= U256::from(40_000_000_000u64) {
604 base_fee_per_gas * 2
605 } else if base_fee_per_gas <= U256::from(100_000_000_000u64) {
606 base_fee_per_gas * 16 / 10
607 } else if base_fee_per_gas <= U256::from(200_000_000_000u64) {
608 base_fee_per_gas * 14 / 10
609 } else {
610 base_fee_per_gas * 12 / 10
611 }
612}
613
614#[cfg(not(target_arch = "wasm32"))]
619pub(crate) fn unused_port() -> u16 {
620 let listener = std::net::TcpListener::bind("127.0.0.1:0")
621 .expect("Failed to create TCP listener to find unused port");
622
623 let local_addr =
624 listener.local_addr().expect("Failed to read TCP listener local_addr to find unused port");
625 local_addr.port()
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631 use crate::types::serde_helpers::deserialize_stringified_numeric;
632 use hex_literal::hex;
633
634 #[test]
635 fn wei_in_ether() {
636 assert_eq!(WEI_IN_ETHER.as_u64(), 1e18 as u64);
637 }
638
639 #[test]
640 fn test_format_ether_unsigned() {
641 let eth = format_ether(WEI_IN_ETHER);
642 assert_eq!(eth.parse::<f64>().unwrap() as u64, 1);
643
644 let eth = format_ether(1395633240123456000_u128);
645 assert_eq!(eth.parse::<f64>().unwrap(), 1.395633240123456);
646
647 let eth = format_ether(U256::from_dec_str("1395633240123456000").unwrap());
648 assert_eq!(eth.parse::<f64>().unwrap(), 1.395633240123456);
649
650 let eth = format_ether(U256::from_dec_str("1395633240123456789").unwrap());
651 assert_eq!(eth, "1.395633240123456789");
652
653 let eth = format_ether(U256::from_dec_str("1005633240123456789").unwrap());
654 assert_eq!(eth, "1.005633240123456789");
655
656 let eth = format_ether(u16::MAX);
657 assert_eq!(eth, "0.000000000000065535");
658
659 let eth = format_ether(u32::MAX);
661 assert_eq!(eth, "0.000000004294967295");
662
663 let eth = format_ether(u64::MAX);
665 assert_eq!(eth, "18.446744073709551615");
666 }
667
668 #[test]
669 fn test_format_ether_signed() {
670 let eth = format_ether(I256::from_dec_str("-1395633240123456000").unwrap());
671 assert_eq!(eth.parse::<f64>().unwrap(), -1.395633240123456);
672
673 let eth = format_ether(I256::from_dec_str("-1395633240123456789").unwrap());
674 assert_eq!(eth, "-1.395633240123456789");
675
676 let eth = format_ether(I256::from_dec_str("1005633240123456789").unwrap());
677 assert_eq!(eth, "1.005633240123456789");
678
679 let eth = format_ether(i8::MIN);
680 assert_eq!(eth, "-0.000000000000000128");
681
682 let eth = format_ether(i8::MAX);
683 assert_eq!(eth, "0.000000000000000127");
684
685 let eth = format_ether(i16::MIN);
686 assert_eq!(eth, "-0.000000000000032768");
687
688 let eth = format_ether(i32::MIN);
690 assert_eq!(eth, "-0.000000002147483648");
691
692 let eth = format_ether(i64::MIN);
694 assert_eq!(eth, "-9.223372036854775808");
695 }
696
697 #[test]
698 fn test_format_units_unsigned() {
699 let gwei_in_ether = format_units(WEI_IN_ETHER, 9).unwrap();
700 assert_eq!(gwei_in_ether.parse::<f64>().unwrap() as u64, 1e9 as u64);
701
702 let eth = format_units(WEI_IN_ETHER, "ether").unwrap();
703 assert_eq!(eth.parse::<f64>().unwrap() as u64, 1);
704
705 let eth = format_units(1395633240123456000_u128, "ether").unwrap();
706 assert_eq!(eth.parse::<f64>().unwrap(), 1.395633240123456);
707
708 let eth =
709 format_units(U256::from_dec_str("1395633240123456000").unwrap(), "ether").unwrap();
710 assert_eq!(eth.parse::<f64>().unwrap(), 1.395633240123456);
711
712 let eth =
713 format_units(U256::from_dec_str("1395633240123456789").unwrap(), "ether").unwrap();
714 assert_eq!(eth, "1.395633240123456789");
715
716 let eth =
717 format_units(U256::from_dec_str("1005633240123456789").unwrap(), "ether").unwrap();
718 assert_eq!(eth, "1.005633240123456789");
719
720 let eth = format_units(u8::MAX, 4).unwrap();
721 assert_eq!(eth, "0.0255");
722
723 let eth = format_units(u16::MAX, "ether").unwrap();
724 assert_eq!(eth, "0.000000000000065535");
725
726 let eth = format_units(u32::MAX, 18).unwrap();
728 assert_eq!(eth, "0.000000004294967295");
729
730 let eth = format_units(u64::MAX, "gwei").unwrap();
732 assert_eq!(eth, "18446744073.709551615");
733
734 let eth = format_units(u128::MAX, 36).unwrap();
735 assert_eq!(eth, "340.282366920938463463374607431768211455");
736
737 let eth = format_units(U256::MAX, 77).unwrap();
738 assert_eq!(
739 eth,
740 "1.15792089237316195423570985008687907853269984665640564039457584007913129639935"
741 );
742
743 let err = format_units(U256::MAX, 78).unwrap_err();
744 assert!(matches!(err, ConversionError::ParseOverflow));
745 }
746
747 #[test]
748 fn test_format_units_signed() {
749 let eth =
750 format_units(I256::from_dec_str("-1395633240123456000").unwrap(), "ether").unwrap();
751 assert_eq!(eth.parse::<f64>().unwrap(), -1.395633240123456);
752
753 let eth =
754 format_units(I256::from_dec_str("-1395633240123456789").unwrap(), "ether").unwrap();
755 assert_eq!(eth, "-1.395633240123456789");
756
757 let eth =
758 format_units(I256::from_dec_str("1005633240123456789").unwrap(), "ether").unwrap();
759 assert_eq!(eth, "1.005633240123456789");
760
761 let eth = format_units(i8::MIN, 4).unwrap();
762 assert_eq!(eth, "-0.0128");
763 assert_eq!(eth.parse::<f64>().unwrap(), -0.0128_f64);
764
765 let eth = format_units(i8::MAX, 4).unwrap();
766 assert_eq!(eth, "0.0127");
767 assert_eq!(eth.parse::<f64>().unwrap(), 0.0127);
768
769 let eth = format_units(i16::MIN, "ether").unwrap();
770 assert_eq!(eth, "-0.000000000000032768");
771
772 let eth = format_units(i32::MIN, 18).unwrap();
774 assert_eq!(eth, "-0.000000002147483648");
775
776 let eth = format_units(i64::MIN, "gwei").unwrap();
778 assert_eq!(eth, "-9223372036.854775808");
779
780 let eth = format_units(i128::MIN, 36).unwrap();
781 assert_eq!(eth, "-170.141183460469231731687303715884105728");
782
783 let eth = format_units(I256::MIN, 76).unwrap();
784 assert_eq!(
785 eth,
786 "-5.7896044618658097711785492504343953926634992332820282019728792003956564819968"
787 );
788
789 let err = format_units(I256::MIN, 77).unwrap_err();
790 assert!(matches!(err, ConversionError::ParseOverflow));
791 }
792
793 #[test]
794 fn parse_large_units() {
795 let decimals = 27u32;
796 let val = "10.55";
797
798 let n: U256 = parse_units(val, decimals).unwrap().into();
799 assert_eq!(n.to_string(), "10550000000000000000000000000");
800 }
801
802 #[test]
803 fn test_parse_units() {
804 let gwei: U256 = parse_units(1.5, 9).unwrap().into();
805 assert_eq!(gwei.as_u64(), 15e8 as u64);
806
807 let token: U256 = parse_units(1163.56926418, 8).unwrap().into();
808 assert_eq!(token.as_u64(), 116356926418);
809
810 let eth_dec_float: U256 = parse_units(1.39563324, "ether").unwrap().into();
811 assert_eq!(eth_dec_float, U256::from_dec_str("1395633240000000000").unwrap());
812
813 let eth_dec_string: U256 = parse_units("1.39563324", "ether").unwrap().into();
814 assert_eq!(eth_dec_string, U256::from_dec_str("1395633240000000000").unwrap());
815
816 let eth: U256 = parse_units(1, "ether").unwrap().into();
817 assert_eq!(eth, WEI_IN_ETHER);
818
819 let val: U256 = parse_units("2.3", "ether").unwrap().into();
820 assert_eq!(val, U256::from_dec_str("2300000000000000000").unwrap());
821
822 let n: U256 = parse_units(".2", 2).unwrap().into();
823 assert_eq!(n, U256::from(20), "leading dot");
824
825 let n: U256 = parse_units("333.21", 2).unwrap().into();
826 assert_eq!(n, U256::from(33321), "trailing dot");
827
828 let n: U256 = parse_units("98766", 16).unwrap().into();
829 assert_eq!(n, U256::from_dec_str("987660000000000000000").unwrap(), "no dot");
830
831 let n: U256 = parse_units("3_3_0", 3).unwrap().into();
832 assert_eq!(n, U256::from(330000), "underscore");
833
834 let n: U256 = parse_units("330", 0).unwrap().into();
835 assert_eq!(n, U256::from(330), "zero decimals");
836
837 let n: U256 = parse_units(".1234", 3).unwrap().into();
838 assert_eq!(n, U256::from(123), "truncate too many decimals");
839
840 assert!(parse_units("1", 80).is_err(), "overflow");
841 assert!(parse_units("1", -1).is_err(), "neg units");
842
843 let two_e30 = U256::from(2) * U256([0x4674edea40000000, 0xc9f2c9cd0, 0x0, 0x0]);
844 let n: U256 = parse_units("2", 30).unwrap().into();
845 assert_eq!(n, two_e30, "2e30");
846
847 let n: U256 = parse_units(".33_319_2", 0).unwrap().into();
848 assert_eq!(n, U256::zero(), "mix");
849
850 let n: U256 = parse_units("", 3).unwrap().into();
851 assert_eq!(n, U256::zero(), "empty");
852 }
853
854 #[test]
855 fn test_signed_parse_units() {
856 let gwei: I256 = parse_units(-1.5, 9).unwrap().into();
857 assert_eq!(gwei.as_i64(), -15e8 as i64);
858
859 let token: I256 = parse_units(-1163.56926418, 8).unwrap().into();
860 assert_eq!(token.as_i64(), -116356926418);
861
862 let eth_dec_float: I256 = parse_units(-1.39563324, "ether").unwrap().into();
863 assert_eq!(eth_dec_float, I256::from_dec_str("-1395633240000000000").unwrap());
864
865 let eth_dec_string: I256 = parse_units("-1.39563324", "ether").unwrap().into();
866 assert_eq!(eth_dec_string, I256::from_dec_str("-1395633240000000000").unwrap());
867
868 let eth: I256 = parse_units(-1, "ether").unwrap().into();
869 assert_eq!(eth, I256::from_raw(WEI_IN_ETHER) * I256::minus_one());
870
871 let val: I256 = parse_units("-2.3", "ether").unwrap().into();
872 assert_eq!(val, I256::from_dec_str("-2300000000000000000").unwrap());
873
874 let n: I256 = parse_units("-.2", 2).unwrap().into();
875 assert_eq!(n, I256::from(-20), "leading dot");
876
877 let n: I256 = parse_units("-333.21", 2).unwrap().into();
878 assert_eq!(n, I256::from(-33321), "trailing dot");
879
880 let n: I256 = parse_units("-98766", 16).unwrap().into();
881 assert_eq!(n, I256::from_dec_str("-987660000000000000000").unwrap(), "no dot");
882
883 let n: I256 = parse_units("-3_3_0", 3).unwrap().into();
884 assert_eq!(n, I256::from(-330000), "underscore");
885
886 let n: I256 = parse_units("-330", 0).unwrap().into();
887 assert_eq!(n, I256::from(-330), "zero decimals");
888
889 let n: I256 = parse_units("-.1234", 3).unwrap().into();
890 assert_eq!(n, I256::from(-123), "truncate too many decimals");
891
892 assert!(parse_units("-1", 80).is_err(), "overflow");
893
894 let two_e30 =
895 I256::from(-2) * I256::from_raw(U256([0x4674edea40000000, 0xc9f2c9cd0, 0x0, 0x0]));
896 let n: I256 = parse_units("-2", 30).unwrap().into();
897 assert_eq!(n, two_e30, "-2e30");
898
899 let n: I256 = parse_units("-.33_319_2", 0).unwrap().into();
900 assert_eq!(n, I256::zero(), "mix");
901
902 let n: I256 = parse_units("-", 3).unwrap().into();
903 assert_eq!(n, I256::zero(), "empty");
904 }
905
906 #[test]
907 fn addr_checksum() {
908 let addr_list = vec![
909 (
911 None,
912 "27b1fdb04752bbc536007a920d24acb045561c26",
913 "0x27b1fdb04752bbc536007a920d24acb045561c26",
914 ),
915 (
916 None,
917 "3599689e6292b81b2d85451025146515070129bb",
918 "0x3599689E6292b81B2d85451025146515070129Bb",
919 ),
920 (
921 None,
922 "42712d45473476b98452f434e72461577d686318",
923 "0x42712D45473476b98452f434e72461577D686318",
924 ),
925 (
926 None,
927 "52908400098527886e0f7030069857d2e4169ee7",
928 "0x52908400098527886E0F7030069857D2E4169EE7",
929 ),
930 (
931 None,
932 "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed",
933 "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
934 ),
935 (
936 None,
937 "6549f4939460de12611948b3f82b88c3c8975323",
938 "0x6549f4939460DE12611948b3f82b88C3C8975323",
939 ),
940 (
941 None,
942 "66f9664f97f2b50f62d13ea064982f936de76657",
943 "0x66f9664f97F2b50F62D13eA064982f936dE76657",
944 ),
945 (
946 None,
947 "88021160c5c792225e4e5452585947470010289d",
948 "0x88021160C5C792225E4E5452585947470010289D",
949 ),
950 (
952 Some(30),
953 "27b1fdb04752bbc536007a920d24acb045561c26",
954 "0x27b1FdB04752BBc536007A920D24ACB045561c26",
955 ),
956 (
957 Some(30),
958 "3599689e6292b81b2d85451025146515070129bb",
959 "0x3599689E6292B81B2D85451025146515070129Bb",
960 ),
961 (
962 Some(30),
963 "42712d45473476b98452f434e72461577d686318",
964 "0x42712D45473476B98452f434E72461577d686318",
965 ),
966 (
967 Some(30),
968 "52908400098527886e0f7030069857d2e4169ee7",
969 "0x52908400098527886E0F7030069857D2E4169ee7",
970 ),
971 (
972 Some(30),
973 "5aaeb6053f3e94c9b9a09f33669435e7ef1beaed",
974 "0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD",
975 ),
976 (
977 Some(30),
978 "6549f4939460de12611948b3f82b88c3c8975323",
979 "0x6549F4939460DE12611948B3F82B88C3C8975323",
980 ),
981 (
982 Some(30),
983 "66f9664f97f2b50f62d13ea064982f936de76657",
984 "0x66F9664f97f2B50F62d13EA064982F936de76657",
985 ),
986 ];
987
988 for (chain_id, addr, checksummed_addr) in addr_list {
989 let addr = addr.parse::<Address>().unwrap();
990 assert_eq!(to_checksum(&addr, chain_id), String::from(checksummed_addr));
991 }
992 }
993
994 #[test]
995 fn checksummed_parse() {
996 let cases = vec![
997 (None, "0x27b1fdb04752bbc536007a920d24acb045561c26", true),
1000 (None, "0x27B1fdb04752bbc536007a920d24acb045561c26", false),
1001 (None, "0x52908400098527886e0f7030069857d2e4169ee7", false),
1003 (None, "0x42712D45473476b98452f434e72461577D686318", true),
1005 (None, "42712D45473476b98452f434e72461577D686318", true),
1006 (None, "0x52908400098527886E0F7030069857D2E4169EE7", true),
1008 (None, "0x52908400098527886E0F7030069857D2E4169EEX", false),
1009 (None, "0x52908400098527886E0F7030069857D2E4169EE70", false),
1010 (None, "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", true),
1012 (None, "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAe1", false),
1013 (Some(30), "0x27b1FdB04752BBc536007A920D24ACB045561c26", true),
1016 (Some(30), "0x27b1FdB04752BBc536007A920D24ACB045561C26", false),
1017 (Some(30), "0x3599689E6292B81B2D85451025146515070129Bb", true),
1019 (Some(30), "3599689E6292B81B2D85451025146515070129Bb", true),
1020 (Some(30), "0x42712D45473476B98452f434E72461577d686318", true),
1022 (Some(30), "0x42712D45473476B98452f434E72461577d686318Z", false),
1023 (Some(30), "0x52908400098527886E0F7030069857D2E4169ee7", true),
1025 (Some(30), "0x52908400098527886E0F7030069857D2E4169ee9", false),
1026 ]; for (chain_id, addr, expected) in cases {
1029 let result = parse_checksummed(addr, chain_id);
1030 assert_eq!(
1031 result.is_ok(),
1032 expected,
1033 "chain_id: {:?} addr: {:?} error: {:?}",
1034 chain_id,
1035 addr,
1036 result.err()
1037 );
1038 }
1039 }
1040
1041 #[test]
1042 fn contract_address() {
1043 let from = "6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0".parse::<Address>().unwrap();
1045 for (nonce, expected) in [
1046 "cd234a471b72ba2f1ccf0a70fcaba648a5eecd8d",
1047 "343c43a37d37dff08ae8c4a11544c718abb4fcf8",
1048 "f778b86fa74e846c4f0a1fbd1335fe81c00a0c91",
1049 "fffd933a0bc612844eaf0c6fe3e5b8e9b6c1d19c",
1050 ]
1051 .iter()
1052 .enumerate()
1053 {
1054 let address = get_contract_address(from, nonce);
1055 assert_eq!(address, expected.parse::<Address>().unwrap());
1056 }
1057 }
1058
1059 #[test]
1060 fn create2_address() {
1062 for (from, salt, init_code, expected) in &[
1063 (
1064 "0000000000000000000000000000000000000000",
1065 "0000000000000000000000000000000000000000000000000000000000000000",
1066 "00",
1067 "4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38",
1068 ),
1069 (
1070 "deadbeef00000000000000000000000000000000",
1071 "0000000000000000000000000000000000000000000000000000000000000000",
1072 "00",
1073 "B928f69Bb1D91Cd65274e3c79d8986362984fDA3",
1074 ),
1075 (
1076 "deadbeef00000000000000000000000000000000",
1077 "000000000000000000000000feed000000000000000000000000000000000000",
1078 "00",
1079 "D04116cDd17beBE565EB2422F2497E06cC1C9833",
1080 ),
1081 (
1082 "0000000000000000000000000000000000000000",
1083 "0000000000000000000000000000000000000000000000000000000000000000",
1084 "deadbeef",
1085 "70f2b2914A2a4b783FaEFb75f459A580616Fcb5e",
1086 ),
1087 (
1088 "00000000000000000000000000000000deadbeef",
1089 "00000000000000000000000000000000000000000000000000000000cafebabe",
1090 "deadbeef",
1091 "60f3f640a8508fC6a86d45DF051962668E1e8AC7",
1092 ),
1093 (
1094 "00000000000000000000000000000000deadbeef",
1095 "00000000000000000000000000000000000000000000000000000000cafebabe",
1096 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
1097 "1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C",
1098 ),
1099 (
1100 "0000000000000000000000000000000000000000",
1101 "0000000000000000000000000000000000000000000000000000000000000000",
1102 "",
1103 "E33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0",
1104 ),
1105 ] {
1106 let from = from.parse::<Address>().unwrap();
1108 let salt = hex::decode(salt).unwrap();
1109 let init_code = hex::decode(init_code).unwrap();
1110 let expected = expected.parse::<Address>().unwrap();
1111 assert_eq!(expected, get_create2_address(from, salt.clone(), init_code.clone()));
1112
1113 let init_code_hash = keccak256(init_code).to_vec();
1115 assert_eq!(expected, get_create2_address_from_hash(from, salt, init_code_hash))
1116 }
1117 }
1118
1119 #[test]
1120 fn bytes32_string_parsing() {
1121 let text_bytes_list = vec![
1122 ("", hex!("0000000000000000000000000000000000000000000000000000000000000000")),
1123 ("A", hex!("4100000000000000000000000000000000000000000000000000000000000000")),
1124 (
1125 "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
1126 hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a303132333435"),
1127 ),
1128 (
1129 "!@#$%^&*(),./;'[]",
1130 hex!("21402324255e262a28292c2e2f3b275b5d000000000000000000000000000000"),
1131 ),
1132 ];
1133
1134 for (text, bytes) in text_bytes_list {
1135 assert_eq!(text, parse_bytes32_string(&bytes).unwrap());
1136 }
1137 }
1138
1139 #[test]
1140 fn bytes32_string_formatting() {
1141 let text_bytes_list = vec![
1142 ("", hex!("0000000000000000000000000000000000000000000000000000000000000000")),
1143 ("A", hex!("4100000000000000000000000000000000000000000000000000000000000000")),
1144 (
1145 "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
1146 hex!("4142434445464748494a4b4c4d4e4f505152535455565758595a303132333435"),
1147 ),
1148 (
1149 "!@#$%^&*(),./;'[]",
1150 hex!("21402324255e262a28292c2e2f3b275b5d000000000000000000000000000000"),
1151 ),
1152 ];
1153
1154 for (text, bytes) in text_bytes_list {
1155 assert_eq!(bytes, format_bytes32_string(text).unwrap());
1156 }
1157 }
1158
1159 #[test]
1160 fn bytes32_string_formatting_too_long() {
1161 assert!(matches!(
1162 format_bytes32_string("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456").unwrap_err(),
1163 ConversionError::TextTooLong
1164 ));
1165 }
1166
1167 #[test]
1168 fn test_eip1559_default_estimator() {
1169 let base_fee_per_gas = U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) - 1;
1172 let rewards: Vec<Vec<U256>> = vec![vec![]];
1173 let (base_fee, priority_fee) = eip1559_default_estimator(base_fee_per_gas, rewards);
1174 assert_eq!(priority_fee, U256::from(EIP1559_FEE_ESTIMATION_DEFAULT_PRIORITY_FEE));
1175 assert_eq!(base_fee, base_fee_surged(base_fee_per_gas));
1176
1177 let base_fee_per_gas = U256::from(EIP1559_FEE_ESTIMATION_PRIORITY_FEE_TRIGGER) + 1;
1180 let rewards: Vec<Vec<U256>> = vec![
1181 vec![100_000_000_000u64.into()],
1182 vec![105_000_000_000u64.into()],
1183 vec![102_000_000_000u64.into()],
1184 ]; let (base_fee, priority_fee) = eip1559_default_estimator(base_fee_per_gas, rewards.clone());
1186 assert_eq!(base_fee, base_fee_surged(base_fee_per_gas));
1187 assert_eq!(priority_fee, estimate_priority_fee(rewards.clone()));
1188
1189 assert_eq!(estimate_priority_fee(rewards), 102_000_000_000u64.into());
1191
1192 let overflow = U256::from(u32::MAX) + 1;
1195 let rewards_overflow: Vec<Vec<U256>> = vec![vec![overflow], vec![overflow]];
1196 assert_eq!(estimate_priority_fee(rewards_overflow), overflow);
1197 }
1198
1199 #[test]
1200 fn int_or_hex_combinations() {
1201 let cases = vec![
1206 ("\"0x0\"", U256::from(0)),
1208 ("\"0x1\"", U256::from(1)),
1209 ("\"0x10\"", U256::from(16)),
1210 ("\"0x100000000000000000000000000000000000000000000000000\"", U256::from_dec_str("1606938044258990275541962092341162602522202993782792835301376").unwrap()),
1211 ("10", U256::from(10)),
1213 ("\"10\"", U256::from(10)),
1214 ("\"115792089237316195423570985008687907853269984665640564039457584007913129639935\"", U256::from_dec_str("115792089237316195423570985008687907853269984665640564039457584007913129639935").unwrap())
1216 ];
1217
1218 #[derive(Deserialize)]
1219 struct TestUint(#[serde(deserialize_with = "deserialize_stringified_numeric")] U256);
1220
1221 for (string, expected) in cases {
1222 let test: TestUint = serde_json::from_str(string)
1223 .unwrap_or_else(|err| panic!("failed to deserialize {string}: {err}"));
1224 assert_eq!(test.0, expected, "expected to deserialize {}", string);
1225 }
1226 }
1227
1228 #[test]
1230 fn test_public_key_to_address() {
1231 let addr = "0Ac1dF02185025F65202660F8167210A80dD5086".parse::<Address>().unwrap();
1232
1233 let pubkey = VerifyingKey::from_sec1_bytes(
1235 &hex::decode("0376698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762")
1236 .unwrap(),
1237 )
1238 .unwrap();
1239 assert_eq!(public_key_to_address(&pubkey), addr);
1240
1241 let pubkey= VerifyingKey::from_sec1_bytes(&hex::decode("0476698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762d46ca56d3dad2ce13213a6f42278dabbb53259f2d92681ea6a0b98197a719be3").unwrap()).unwrap();
1243 assert_eq!(public_key_to_address(&pubkey), addr);
1244 }
1245
1246 #[test]
1247 fn test_raw_public_key_to_address() {
1248 let addr = "0Ac1dF02185025F65202660F8167210A80dD5086".parse::<Address>().unwrap();
1249
1250 let pubkey_bytes = hex::decode("76698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762d46ca56d3dad2ce13213a6f42278dabbb53259f2d92681ea6a0b98197a719be3").unwrap();
1251
1252 assert_eq!(raw_public_key_to_address(pubkey_bytes), addr);
1253 }
1254
1255 #[test]
1256 #[should_panic]
1257 fn test_raw_public_key_to_address_panics() {
1258 let fake_pkb = vec![];
1259
1260 raw_public_key_to_address(fake_pkb);
1261 }
1262}