Skip to content

Commit

Permalink
feat: improve errors messages (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yashiru authored Sep 11, 2023
1 parent 8a33aa1 commit fd3bccc
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 27 deletions.
10 changes: 2 additions & 8 deletions install
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,8 @@
# Build
cargo build --release

# Create a Binary Tarball
tar czvf evm-rs.tar.gz -C target/release evm-rs

# Extract the tarball
tar xzvf evm-rs.tar.gz

# Move the binary to a global path
sudo mv target/release/evm-rs /usr/local/bin/

echo -e "\x1b[32mInstallation completed\x1b[0m"
evm-rs --help
echo -e "\x1b[32mInstallation completed!\x1b[0m"
echo -e "Run '\x1b[35mevm-rs --help\x1b[0m' to see the usage."
3 changes: 0 additions & 3 deletions src/core_module/utils/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ pub enum ExecutionError {
StackTooDeep,

// General execution errors
InvalidFile,
Revert(Vec<u8>),
RevertWithoutData,
NotImplemented(u8),
Expand All @@ -38,7 +37,6 @@ impl fmt::Display for ExecutionError {
ExecutionError::StackTooDeep => {
write!(f, "Stack too deep. Maximum stack size is 1024 words")
}
ExecutionError::InvalidFile => write!(f, "Invalid file"),
ExecutionError::AccountNotFound => {
write!(f, "Trying to access non-existent account state")
}
Expand Down Expand Up @@ -78,7 +76,6 @@ impl PartialEq for ExecutionError {
| (StackTooSmall, StackTooSmall)
| (InvalidJumpDestination, InvalidJumpDestination)
| (StackTooDeep, StackTooDeep)
| (InvalidFile, InvalidFile)
| (RevertWithoutData, RevertWithoutData) => true,
(InvalidOpcode(a), InvalidOpcode(b)) => a == b,
(NotImplemented(a), NotImplemented(b)) => a == b,
Expand Down
102 changes: 86 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() -> Result<(), ExecutionError> {
let mut address: Option<[u8; 20]> = Some([0xab; 20]);
let mut value: Option<[u8; 32]> = None;
let mut data: Option<Vec<u8>> = None;
let mut bytecodePath: String = String::from("");
let mut bytecode_path: String;

/* -------------------------------------------------------------------------- */
/* Fetch arguments */
Expand All @@ -30,7 +30,11 @@ fn main() -> Result<(), ExecutionError> {

// Print version
if args.contains(&"--version".to_string()) {
println!("evm-rs version: {}", env!("CARGO_PKG_VERSION"));
println!(
"{}: {}",
"evm-rs version".magenta(),
env!("CARGO_PKG_VERSION").green()
);
return Ok(());
}

Expand All @@ -41,6 +45,11 @@ fn main() -> Result<(), ExecutionError> {
.map(|p| &args[p + 1]);

if let Some(caller_arg) = caller_arg {
if caller_arg.len() != 42 {
unexpected_arg_value("Caller", "an address");
return Ok(());
}

let bytes =
hex::decode(&caller_arg[2..]).expect(&"Invalid argument: --caller".red().to_string());
caller = bytes
Expand All @@ -55,6 +64,11 @@ fn main() -> Result<(), ExecutionError> {
.map(|p| &args[p + 1]);

if let Some(origin_arg) = origin_arg {
if origin_arg.len() != 42 {
unexpected_arg_value("Origin", "an address");
return Ok(());
}

let bytes =
hex::decode(&origin_arg[2..]).expect(&"Invalid argument: --origin".red().to_string());
origin = Some(
Expand All @@ -71,6 +85,11 @@ fn main() -> Result<(), ExecutionError> {
.map(|p| &args[p + 1]);

if let Some(address_arg) = address_arg {
if address_arg.len() != 42 {
unexpected_arg_value("Address", "an address");
return Ok(());
}

let bytes =
hex::decode(&address_arg[2..]).expect(&"Invalid argument: --address".red().to_string());
address = Some(
Expand All @@ -87,6 +106,11 @@ fn main() -> Result<(), ExecutionError> {
.map(|p| &args[p + 1]);

if let Some(value_arg) = value_arg {
if value_arg.len() < 3 || !value_arg.starts_with("0x") {
unexpected_arg_value("Value", "a hex value");
return Ok(());
}

let bytes =
hex::decode(&value_arg[2..]).expect(&"Invalid argument: --value".red().to_string());

Expand All @@ -104,6 +128,11 @@ fn main() -> Result<(), ExecutionError> {
.map(|p| &args[p + 1]);

if let Some(data_arg) = data_arg {
if data_arg.len() < 3 || !data_arg.starts_with("0x") {
unexpected_arg_value("Data", "a hex value");
return Ok(());
}

let bytes =
hex::decode(&data_arg[2..]).expect(&"Invalid argument: --data".red().to_string());
data = Some(
Expand All @@ -118,21 +147,19 @@ fn main() -> Result<(), ExecutionError> {
if args.len() > 1 {
// Manage the current directory and compute the full path
let current_dir = env::current_dir().unwrap();
bytecodePath = current_dir.to_str().unwrap().to_string();
bytecodePath.push_str("/");
bytecodePath.push_str(&args[args.len() - 1]);
bytecode_path = current_dir.to_str().unwrap().to_string();
bytecode_path.push_str("/");
bytecode_path.push_str(&args[args.len() - 1]);
} else {
print_help();
return Ok(());
}
// print path
println!("Bytecode path: {}", bytecodePath);

// Create a new interpreter
let mut interpreter =
core_module::runner::Runner::new(caller, origin, address, value, data, None);

let result = fs::read_to_string(bytecodePath.to_string());
let result = fs::read_to_string(bytecode_path.to_string());

match result {
Ok(file_content) => {
Expand All @@ -142,22 +169,65 @@ fn main() -> Result<(), ExecutionError> {
let _ = interpreter.interpret(bytecode, Some(255), true);
}
Err(_) => {
return Err(ExecutionError::InvalidFile);
// Print the error
println!("{} {}", "Error:".red(), "file not found");
println!(
"\n Run this command with {} for more information.",
"--help".green()
);
return Ok(());
}
}

Ok(())
}

fn unexpected_arg_value(arg: &str, arg_type: &str) {
println!(
"{} unexpected value for '{}' argument.",
"Error:".red(),
format!("--{}", arg.to_lowercase()).yellow()
);
println!(" {} should be {arg_type}.", arg.yellow());
println!(
"\n Run this command with {} for more information.",
"--help".green()
);
}

fn print_help() {
println!("Execute arbitrary bytecode on the Ethereum Virtual Machine (EVM)");
println!("\nUsage: evm-rs [OPTIONS] [args]...\n");
println!("OPTIONS:");
println!(" --address [<ADDRESS>] Override the default address of the contract containing the bytecode to be executed");
println!(" --caller [<ADDRESS>] Override the default caller address");
println!(
" --data [<HEX_DATA>] Override the default call data to be passed to the contract"
"\nUsage: {} [{}] [{}] <{}>",
"evm-rs".green(),
"OPTIONS".magenta(),
"args".blue(),
"filePath".cyan()
);
println!(
" {} should be a path to a file containing the bytecode to be executed.\n",
"filePath".cyan()
);
println!("Options:");
println!(" --{} <{}> Override the default address of the contract containing the bytecode to be executed", "address".magenta(), "ADDRESS".blue());
println!(
" --{} <{}> Override the default caller address",
"caller".magenta(),
"ADDRESS".blue()
);
println!(
" --{} <{}> Override the default calldata to be passed to the callee contract",
"data".magenta(),
"HEX_DATA".blue()
);
println!(
" --{} <{}> Override the default origin address",
"origin".magenta(),
"ADDRESS".blue()
);
println!(
" --{} <{}> Override the default value to be sent to the contract",
"value".magenta(),
"HEX_VALUE".blue()
);
println!(" --origin [<ADDRESS>] Override the default origin address");
println!(" --value [<HEX_VALUE>] Override the default value to be sent to the contract");
}

0 comments on commit fd3bccc

Please sign in to comment.