Skip to content

Commit

Permalink
Merge branch 'foundry-rs:master' into 5-bug-release-workflow-failed
Browse files Browse the repository at this point in the history
  • Loading branch information
Dargon789 authored Dec 2, 2024
2 parents 15758c0 + ac81a53 commit b68c7fc
Show file tree
Hide file tree
Showing 102 changed files with 3,060 additions and 1,989 deletions.
604 changes: 322 additions & 282 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ alloy-transport = { version = "0.6.4", default-features = false }
alloy-transport-http = { version = "0.6.4", default-features = false }
alloy-transport-ipc = { version = "0.6.4", default-features = false }
alloy-transport-ws = { version = "0.6.4", default-features = false }
alloy-node-bindings = { version = "0.6.4", default-features = false }

## alloy-core
alloy-dyn-abi = "0.8.11"
Expand Down
11 changes: 4 additions & 7 deletions crates/anvil/src/eth/backend/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3013,11 +3013,8 @@ pub fn prove_storage(storage: &HashMap<U256, U256>, keys: &[B256]) -> Vec<Vec<By
}

pub fn is_arbitrum(chain_id: u64) -> bool {
matches!(
NamedChain::try_from(chain_id),
Ok(NamedChain::Arbitrum |
NamedChain::ArbitrumTestnet |
NamedChain::ArbitrumGoerli |
NamedChain::ArbitrumNova)
)
if let Ok(chain) = NamedChain::try_from(chain_id) {
return chain.is_arbitrum()
}
false
}
6 changes: 3 additions & 3 deletions crates/anvil/src/eth/otterscan/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn mentions_address(trace: LocalizedTransactionTrace, address: Address) -> O

/// Converts the list of traces for a transaction into the expected Otterscan format.
///
/// Follows format specified in the [`ots_traceTransaction`](https://github.com/otterscan/otterscan/blob/develop/docs/custom-jsonrpc.md#ots_tracetransaction) spec.
/// Follows format specified in the [`ots_traceTransaction`](https://github.com/otterscan/otterscan/blob/main/docs/custom-jsonrpc.md#ots_tracetransaction) spec.
pub fn batch_build_ots_traces(traces: Vec<LocalizedTransactionTrace>) -> Vec<TraceEntry> {
traces
.into_iter()
Expand Down Expand Up @@ -350,7 +350,7 @@ impl EthApi {
/// their `gas_used`. This would be extremely inefficient in a real blockchain RPC, but we can
/// get away with that in this context.
///
/// The [original spec](https://github.com/otterscan/otterscan/blob/develop/docs/custom-jsonrpc.md#ots_getblockdetails)
/// The [original spec](https://github.com/otterscan/otterscan/blob/main/docs/custom-jsonrpc.md#ots_getblockdetails)
/// also mentions we can hardcode `transactions` and `logsBloom` to an empty array to save
/// bandwidth, because fields weren't intended to be used in the Otterscan UI at this point.
///
Expand Down Expand Up @@ -402,7 +402,7 @@ impl EthApi {
/// Fetches all receipts for the blocks's transactions, as required by the
/// [`ots_getBlockTransactions`] endpoint spec, and returns the final response object.
///
/// [`ots_getBlockTransactions`]: https://github.com/otterscan/otterscan/blob/develop/docs/custom-jsonrpc.md#ots_getblockdetails
/// [`ots_getBlockTransactions`]: https://github.com/otterscan/otterscan/blob/main/docs/custom-jsonrpc.md#ots_getblockdetails
pub async fn build_ots_block_tx(
&self,
mut block: AnyRpcBlock,
Expand Down
1 change: 1 addition & 0 deletions crates/cast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ tikv-jemallocator = { workspace = true, optional = true }
[dev-dependencies]
anvil.workspace = true
foundry-test-utils.workspace = true
alloy-node-bindings.workspace = true

async-trait.workspace = true
divan.workspace = true
Expand Down
32 changes: 26 additions & 6 deletions crates/cast/bin/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,8 @@ pub enum CastSubcommand {
///
/// Similar to `abi-decode --input`, but function selector MUST be prefixed in `calldata`
/// string
#[command(visible_aliases = &["--calldata-decode", "cdd"])]
CalldataDecode {
#[command(visible_aliases = &["calldata-decode", "--calldata-decode", "cdd"])]
DecodeCalldata {
/// The function signature in the format `<name>(<in-types>)(<out-types>)`.
sig: String,

Expand All @@ -524,19 +524,39 @@ pub enum CastSubcommand {
/// Decode ABI-encoded string.
///
/// Similar to `calldata-decode --input`, but the function argument is a `string`
#[command(visible_aliases = &["--string-decode", "sd"])]
StringDecode {
#[command(visible_aliases = &["string-decode", "--string-decode", "sd"])]
DecodeString {
/// The ABI-encoded string.
data: String,
},

/// Decode event data.
#[command(visible_aliases = &["event-decode", "--event-decode", "ed"])]
DecodeEvent {
/// The event signature. If none provided then tries to decode from local cache or `https://api.openchain.xyz`.
#[arg(long, visible_alias = "event-sig")]
sig: Option<String>,
/// The event data to decode.
data: String,
},

/// Decode custom error data.
#[command(visible_aliases = &["error-decode", "--error-decode", "erd"])]
DecodeError {
/// The error signature. If none provided then tries to decode from local cache or `https://api.openchain.xyz`.
#[arg(long, visible_alias = "error-sig")]
sig: Option<String>,
/// The error data to decode.
data: String,
},

/// Decode ABI-encoded input or output data.
///
/// Defaults to decoding output data. To decode input data pass --input.
///
/// When passing `--input`, function selector must NOT be prefixed in `calldata` string
#[command(name = "abi-decode", visible_aliases = &["ad", "--abi-decode"])]
AbiDecode {
#[command(name = "decode-abi", visible_aliases = &["abi-decode", "--abi-decode", "ad"])]
DecodeAbi {
/// The function signature in the format `<name>(<in-types>)(<out-types>)`.
sig: String,

Expand Down
27 changes: 23 additions & 4 deletions crates/cast/bin/cmd/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use foundry_cli::{
opts::{EthereumOpts, TransactionOpts},
utils::{self, handle_traces, parse_ether_value, TraceResult},
};
use foundry_common::ens::NameOrAddress;
use foundry_common::{ens::NameOrAddress, shell};
use foundry_compilers::artifacts::EvmVersion;
use foundry_config::{
figment::{
Expand All @@ -18,7 +18,11 @@ use foundry_config::{
},
Config,
};
use foundry_evm::{executors::TracingExecutor, opts::EvmOpts};
use foundry_evm::{
executors::TracingExecutor,
opts::EvmOpts,
traces::{InternalTraceMode, TraceMode},
};
use std::str::FromStr;

/// CLI arguments for `cast call`.
Expand Down Expand Up @@ -175,15 +179,30 @@ impl CallArgs {
config.fork_block_number = Some(block_number);
}

let create2_deployer = evm_opts.create2_deployer;
let (mut env, fork, chain, alphanet) =
TracingExecutor::get_fork_material(&config, evm_opts).await?;

// modify settings that usually set in eth_call
env.cfg.disable_block_gas_limit = true;
env.block.gas_limit = U256::MAX;

let mut executor =
TracingExecutor::new(env, fork, evm_version, debug, decode_internal, alphanet);
let trace_mode = TraceMode::Call
.with_debug(debug)
.with_decode_internal(if decode_internal {
InternalTraceMode::Full
} else {
InternalTraceMode::None
})
.with_state_changes(shell::verbosity() > 4);
let mut executor = TracingExecutor::new(
env,
fork,
evm_version,
trace_mode,
alphanet,
create2_deployer,
);

let value = tx.value.unwrap_or_default();
let input = tx.inner.input.into_input().unwrap_or_default();
Expand Down
28 changes: 19 additions & 9 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use foundry_cli::{
opts::{EtherscanOpts, RpcOpts},
utils::{handle_traces, init_progress, TraceResult},
};
use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE};
use foundry_common::{is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE};
use foundry_compilers::artifacts::EvmVersion;
use foundry_config::{
figment::{
Expand All @@ -23,6 +23,7 @@ use foundry_config::{
use foundry_evm::{
executors::{EvmError, TracingExecutor},
opts::EvmOpts,
traces::{InternalTraceMode, TraceMode},
utils::configure_tx_env,
};

Expand Down Expand Up @@ -107,11 +108,9 @@ impl RunArgs {
let compute_units_per_second =
if self.no_rate_limit { Some(u64::MAX) } else { self.compute_units_per_second };

let provider = foundry_common::provider::ProviderBuilder::new(
&config.get_rpc_url_or_localhost_http()?,
)
.compute_units_per_second_opt(compute_units_per_second)
.build()?;
let provider = foundry_cli::utils::get_provider_builder(&config)?
.compute_units_per_second_opt(compute_units_per_second)
.build()?;

let tx_hash = self.tx_hash.parse().wrap_err("invalid tx hash")?;
let tx = provider
Expand All @@ -138,6 +137,7 @@ impl RunArgs {
// we need to fork off the parent block
config.fork_block_number = Some(tx_block_number - 1);

let create2_deployer = evm_opts.create2_deployer;
let (mut env, fork, chain, alphanet) =
TracingExecutor::get_fork_material(&config, evm_opts).await?;

Expand All @@ -163,20 +163,30 @@ impl RunArgs {
}
}

let trace_mode = TraceMode::Call
.with_debug(self.debug)
.with_decode_internal(if self.decode_internal {
InternalTraceMode::Full
} else {
InternalTraceMode::None
})
.with_state_changes(shell::verbosity() > 4);
let mut executor = TracingExecutor::new(
env.clone(),
fork,
evm_version,
self.debug,
self.decode_internal,
trace_mode,
alphanet,
create2_deployer,
);
let mut env =
EnvWithHandlerCfg::new_with_spec_id(Box::new(env.clone()), executor.spec_id());

// Set the state to the moment right before the transaction
if !self.quick {
sh_println!("Executing previous transactions from the block.")?;
if !shell::is_json() {
sh_println!("Executing previous transactions from the block.")?;
}

if let Some(block) = block {
let pb = init_progress(block.transactions.len() as u64, "tx");
Expand Down
59 changes: 54 additions & 5 deletions crates/cast/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[macro_use]
extern crate tracing;

use alloy_dyn_abi::DynSolValue;
use alloy_dyn_abi::{DynSolValue, ErrorExt, EventExt};
use alloy_primitives::{eip191_hash_message, hex, keccak256, Address, B256};
use alloy_provider::Provider;
use alloy_rpc_types::{BlockId, BlockNumberOrTag::Latest};
Expand All @@ -11,7 +11,7 @@ use clap_complete::generate;
use eyre::Result;
use foundry_cli::{handler, utils};
use foundry_common::{
abi::get_event,
abi::{get_error, get_event},
ens::{namehash, ProviderEnsExt},
fmt::{format_tokens, format_tokens_raw, format_uint_exp},
fs,
Expand All @@ -30,6 +30,7 @@ pub mod cmd;
pub mod tx;

use args::{Cast as CastArgs, CastSubcommand, ToBaseArgs};
use cast::traces::identifier::SignaturesIdentifier;

#[macro_use]
extern crate foundry_common;
Expand Down Expand Up @@ -189,7 +190,7 @@ async fn main_args(args: CastArgs) -> Result<()> {
}

// ABI encoding & decoding
CastSubcommand::AbiDecode { sig, calldata, input } => {
CastSubcommand::DecodeAbi { sig, calldata, input } => {
let tokens = SimpleCast::abi_decode(&sig, &calldata, input)?;
print_tokens(&tokens);
}
Expand All @@ -200,17 +201,65 @@ async fn main_args(args: CastArgs) -> Result<()> {
sh_println!("{}", SimpleCast::abi_encode_packed(&sig, &args)?)?
}
}
CastSubcommand::CalldataDecode { sig, calldata } => {
CastSubcommand::DecodeCalldata { sig, calldata } => {
let tokens = SimpleCast::calldata_decode(&sig, &calldata, true)?;
print_tokens(&tokens);
}
CastSubcommand::CalldataEncode { sig, args } => {
sh_println!("{}", SimpleCast::calldata_encode(sig, &args)?)?;
}
CastSubcommand::StringDecode { data } => {
CastSubcommand::DecodeString { data } => {
let tokens = SimpleCast::calldata_decode("Any(string)", &data, true)?;
print_tokens(&tokens);
}
CastSubcommand::DecodeEvent { sig, data } => {
let decoded_event = if let Some(event_sig) = sig {
get_event(event_sig.as_str())?.decode_log_parts(None, &hex::decode(data)?, false)?
} else {
let data = data.strip_prefix("0x").unwrap_or(data.as_str());
let selector = data.get(..64).unwrap_or_default();
let identified_event =
SignaturesIdentifier::new(Config::foundry_cache_dir(), false)?
.write()
.await
.identify_event(&hex::decode(selector)?)
.await;
if let Some(event) = identified_event {
let _ = sh_println!("{}", event.signature());
let data = data.get(64..).unwrap_or_default();
get_event(event.signature().as_str())?.decode_log_parts(
None,
&hex::decode(data)?,
false,
)?
} else {
eyre::bail!("No matching event signature found for selector `{selector}`")
}
};
print_tokens(&decoded_event.body);
}
CastSubcommand::DecodeError { sig, data } => {
let error = if let Some(err_sig) = sig {
get_error(err_sig.as_str())?
} else {
let data = data.strip_prefix("0x").unwrap_or(data.as_str());
let selector = data.get(..8).unwrap_or_default();
let identified_error =
SignaturesIdentifier::new(Config::foundry_cache_dir(), false)?
.write()
.await
.identify_error(&hex::decode(selector)?)
.await;
if let Some(error) = identified_error {
let _ = sh_println!("{}", error.signature());
error
} else {
eyre::bail!("No matching error signature found for selector `{selector}`")
}
};
let decoded_error = error.decode_error(&hex::decode(data)?)?;
print_tokens(&decoded_error.body);
}
CastSubcommand::Interface(cmd) => cmd.run().await?,
CastSubcommand::CreationCode(cmd) => cmd.run().await?,
CastSubcommand::ConstructorArgs(cmd) => cmd.run().await?,
Expand Down
21 changes: 20 additions & 1 deletion crates/cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,7 @@ impl SimpleCast {
pub fn disassemble(code: &[u8]) -> Result<String> {
let mut output = String::new();

for step in decode_instructions(code) {
for step in decode_instructions(code)? {
write!(output, "{:08x}: ", step.pc)?;

if let Some(op) = step.op {
Expand Down Expand Up @@ -2290,4 +2290,23 @@ mod tests {
r#"["0x2b5df5f0757397573e8ff34a8b987b21680357de1f6c8d10273aa528a851eaca","0x","0x","0x2838ac1d2d2721ba883169179b48480b2ba4f43d70fcf806956746bd9e83f903","0x","0xe46fff283b0ab96a32a7cc375cecc3ed7b6303a43d64e0a12eceb0bc6bd87549","0x","0x1d818c1c414c665a9c9a0e0c0ef1ef87cacb380b8c1f6223cb2a68a4b2d023f5","0x","0x","0x","0x236e8f61ecde6abfebc6c529441f782f62469d8a2cc47b7aace2c136bd3b1ff0","0x","0x","0x","0x","0x"]"#
)
}

#[test]
fn disassemble_incomplete_sequence() {
let incomplete = &hex!("60"); // PUSH1
let disassembled = Cast::disassemble(incomplete);
assert!(disassembled.is_err());

let complete = &hex!("6000"); // PUSH1 0x00
let disassembled = Cast::disassemble(complete);
assert!(disassembled.is_ok());

let incomplete = &hex!("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // PUSH32 with 31 bytes
let disassembled = Cast::disassemble(incomplete);
assert!(disassembled.is_err());

let complete = &hex!("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // PUSH32 with 32 bytes
let disassembled = Cast::disassemble(complete);
assert!(disassembled.is_ok());
}
}
Loading

0 comments on commit b68c7fc

Please sign in to comment.