Skip to content

Commit 52860c8

Browse files
authored
perf: replace hex with const-hex (foundry-rs#5599)
1 parent 56131bf commit 52860c8

File tree

13 files changed

+53
-72
lines changed

13 files changed

+53
-72
lines changed

Cargo.lock

Lines changed: 18 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ ethers-etherscan = { git = "https://github.com/gakonst/ethers-rs", default-featu
119119
ethers-solc = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
120120

121121
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
122+
hex = { package = "const-hex", version = "1.6", features = ["hex"] }
122123
solang-parser = "=0.3.1"
123124

124125
#[patch."https://github.com/gakonst/ethers-rs"]

cast/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ ethers-providers = { workspace = true }
2020
ethers-signers = { workspace = true }
2121
futures = "0.3"
2222
eyre = "0.6"
23-
rustc-hex = "2"
2423
serde = "1"
2524
serde_json = "1"
2625
chrono.workspace = true
27-
hex = "0.4"
26+
hex.workspace = true
2827
rayon = "1"
2928

3029
# aws

cast/src/lib.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ pub use rusoto_core::{
2828
request::HttpClient as AwsHttpClient, Client as AwsClient,
2929
};
3030
pub use rusoto_kms::KmsClient;
31-
use rustc_hex::{FromHexIter, ToHex};
3231
use std::{
3332
path::PathBuf,
3433
str::FromStr,
@@ -915,8 +914,7 @@ impl SimpleCast {
915914
/// }
916915
/// ```
917916
pub fn from_utf8(s: &str) -> String {
918-
let s: String = s.as_bytes().to_hex();
919-
format!("0x{s}")
917+
hex::encode_prefixed(s)
920918
}
921919

922920
/// Converts hex data into text data
@@ -935,13 +933,11 @@ impl SimpleCast {
935933
/// }
936934
/// ```
937935
pub fn to_ascii(hex: &str) -> Result<String> {
938-
let hex_trimmed = hex.trim_start_matches("0x");
939-
let iter = FromHexIter::new(hex_trimmed);
940-
let mut ascii = String::new();
941-
for letter in iter.collect::<Vec<_>>() {
942-
ascii.push(letter? as char);
936+
let bytes = hex::decode(hex)?;
937+
if !bytes.iter().all(u8::is_ascii) {
938+
return Err(eyre::eyre!("Invalid ASCII bytes"))
943939
}
944-
Ok(ascii)
940+
Ok(String::from_utf8(bytes).unwrap())
945941
}
946942

947943
/// Converts fixed point number into specified number of decimals
@@ -1457,7 +1453,7 @@ impl SimpleCast {
14571453
}
14581454
};
14591455
let calldata = match encode_args(&func, args) {
1460-
Ok(res) => res.to_hex::<String>(),
1456+
Ok(res) => hex::encode(res),
14611457
Err(e) => eyre::bail!("Could not ABI encode the function and arguments. Did you pass in the right types?\nError\n{}", e),
14621458
};
14631459
let encoded = &calldata[8..];
@@ -1482,7 +1478,7 @@ impl SimpleCast {
14821478
pub fn calldata_encode(sig: impl AsRef<str>, args: &[impl AsRef<str>]) -> Result<String> {
14831479
let func = HumanReadableParser::parse_function(sig.as_ref())?;
14841480
let calldata = encode_args(&func, args)?;
1485-
Ok(format!("0x{}", calldata.to_hex::<String>()))
1481+
Ok(hex::encode_prefixed(calldata))
14861482
}
14871483

14881484
/// Generates an interface in solidity from either a local file ABI or a verified contract on
@@ -1609,8 +1605,7 @@ impl SimpleCast {
16091605
}
16101606
}
16111607

1612-
let namehash: String = node.to_hex();
1613-
Ok(format!("0x{namehash}"))
1608+
Ok(hex::encode_prefixed(node))
16141609
}
16151610

16161611
/// Keccak-256 hashes arbitrary data

cli/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,11 @@ tempfile = "3"
6060
# misc
6161
eyre = "0.6"
6262
color-eyre = "0.6"
63-
rustc-hex = "2"
6463
serde = { version = "1", features = ["derive"] }
6564
serde_json = "1"
6665
regex = { version = "1", default-features = false }
6766
rpassword = "7"
68-
hex = "0.4"
67+
hex = { workspace = true, features = ["serde"] }
6968
itertools = "0.10"
7069
proptest = "1"
7170
semver = "1"

cli/src/cast.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use foundry_common::{
2222
},
2323
};
2424
use foundry_config::Config;
25-
use rustc_hex::ToHex;
2625
use std::time::Instant;
2726

2827
#[tokio::main]
@@ -83,21 +82,9 @@ async fn main() -> eyre::Result<()> {
8382
Subcommands::ToHexdata { input } => {
8483
let value = stdin::unwrap_line(input)?;
8584
let output = match value {
86-
s if s.starts_with('@') => {
87-
let var = std::env::var(&s[1..])?;
88-
var.as_bytes().to_hex()
89-
}
90-
s if s.starts_with('/') => {
91-
let input = fs::read(s)?;
92-
input.to_hex()
93-
}
94-
s => {
95-
let mut output = String::new();
96-
for s in s.split(':') {
97-
output.push_str(&s.trim_start_matches("0x").to_lowercase())
98-
}
99-
output
100-
}
85+
s if s.starts_with('@') => hex::encode(std::env::var(&s[1..])?),
86+
s if s.starts_with('/') => hex::encode(fs::read(s)?),
87+
s => s.split(':').map(|s| s.trim_start_matches("0x").to_lowercase()).collect(),
10188
};
10289
println!("0x{output}");
10390
}

cli/src/cmd/forge/create.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use ethers::{
1818
};
1919
use eyre::Context;
2020
use foundry_common::{abi::parse_tokens, compile, estimate_eip1559_fees};
21-
use rustc_hex::ToHex;
2221
use serde_json::json;
2322
use std::{path::PathBuf, sync::Arc};
2423

@@ -263,10 +262,9 @@ impl CreateArgs {
263262
let code = Vec::new();
264263
let encoded_args = abi
265264
.constructor()
266-
.ok_or(eyre::eyre!("could not find constructor"))?
267-
.encode_input(code, &args)?
268-
.to_hex::<String>();
269-
constructor_args = Some(encoded_args);
265+
.ok_or_else(|| eyre::eyre!("could not find constructor"))?
266+
.encode_input(code, &args)?;
267+
constructor_args = Some(hex::encode(encoded_args));
270268
}
271269

272270
self.verify_preflight_check(constructor_args.clone(), chain).await?;

cli/src/cmd/forge/verify/etherscan/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use foundry_utils::Retry;
2424
use futures::FutureExt;
2525
use once_cell::sync::Lazy;
2626
use regex::Regex;
27-
use rustc_hex::ToHex;
2827
use semver::{BuildMetadata, Version};
2928
use std::{
3029
fmt::Debug,
@@ -432,8 +431,8 @@ impl EtherscanVerificationProvider {
432431
let encoded_args = encode_args(
433432
&func,
434433
&read_constructor_args_file(constructor_args_path.to_path_buf())?,
435-
)?
436-
.to_hex::<String>();
434+
)?;
435+
let encoded_args = hex::encode(encoded_args);
437436
return Ok(Some(encoded_args[8..].into()))
438437
}
439438

evm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ethers = { workspace = true, features = ["ethers-solc"] }
1919
# Encoding/decoding
2020
serde_json = "1"
2121
serde = "1"
22-
hex = "0.4"
22+
hex.workspace = true
2323
jsonpath_lib = "0.3"
2424

2525
# Error handling

evm/src/executor/inspector/cheatcodes/ext.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ use ethers::{
77
};
88
use foundry_common::{fmt::*, fs, get_artifact_path};
99
use foundry_config::fs_permissions::FsAccessKind;
10-
use hex::FromHex;
1110
use serde::Deserialize;
1211
use serde_json::Value;
13-
use std::{collections::BTreeMap, env, path::Path, process::Command, str::FromStr};
12+
use std::{collections::BTreeMap, env, path::Path, process::Command};
1413

1514
/// Invokes a `Command` with the given args and returns the abi encoded response
1615
///
@@ -211,22 +210,18 @@ fn value_to_token(value: &Value) -> Result<Token> {
211210
Err(fmt_err!("Unsupported value: {number:?}"))
212211
}
213212
Value::String(string) => {
214-
if let Some(val) = string.strip_prefix("0x") {
215-
// If it can decoded as an address, it's an address
216-
if let Ok(addr) = H160::from_str(string) {
217-
Ok(Token::Address(addr))
218-
} else if hex::decode(val).is_ok() {
219-
// if length == 32 bytes, then encode as Bytes32, else Bytes
220-
Ok(if val.len() == 64 {
221-
Token::FixedBytes(Vec::from_hex(val).unwrap())
222-
} else {
223-
Token::Bytes(Vec::from_hex(val).unwrap())
224-
})
225-
} else {
226-
// If incorrect length, pad 0 at the beginning
227-
let arr = format!("0{val}");
228-
Ok(Token::Bytes(Vec::from_hex(arr).unwrap()))
213+
if let Some(mut val) = string.strip_prefix("0x") {
214+
let s;
215+
if val.len() % 2 != 0 {
216+
s = format!("0{}", val);
217+
val = &s[..];
229218
}
219+
let bytes = hex::decode(val)?;
220+
Ok(match bytes.len() {
221+
20 => Token::Address(Address::from_slice(&bytes)),
222+
32 => Token::FixedBytes(bytes),
223+
_ => Token::Bytes(bytes),
224+
})
230225
} else {
231226
Ok(Token::String(string.to_owned()))
232227
}

0 commit comments

Comments
 (0)