Skip to content

Commit

Permalink
Merge branch 'master' into fix/cross-platform-build
Browse files Browse the repository at this point in the history
  • Loading branch information
gakonst committed Dec 19, 2021
2 parents 799387e + 8dfa2fa commit daebf1b
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 109 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Foundry consists of:

![demo](./assets/demo.svg)

## Dependencies
Currently both Forge and Cast rely on the [libudev-dev](https://packages.debian.org/sid/libudev-dev) package. This package may be preinstalled for your system, but is also available in most packages managers.

## Forge

```
Expand Down
6 changes: 3 additions & 3 deletions cast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- [x] `--from-ascii` (with `--from-utf8` alias)
- [ ] `--from-bin`
- [ ] `--from-fix`
- [ ] `--from-wei`
- [x] `--from-wei`
- [ ] `--max-int`
- [x] `--max-uint`
- [ ] `--min-int`
Expand Down Expand Up @@ -35,7 +35,7 @@
- [x] `calldata`
- [x] `chain`
- [x] `chain-id`
- [ ] `code`
- [x] `code`
- [ ] `debug`
- [ ] `estimate`
- [ ] `etherscan-source`
Expand All @@ -56,4 +56,4 @@
- [x] `send` (partial)
- [ ] `sign`
- [x] `storage`
- [ ] `tx`
- [x] `tx`
95 changes: 87 additions & 8 deletions cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,20 @@ where
let res = self.provider.call(&tx, None).await?;

// decode args into tokens
let res = func.decode_output(res.as_ref())?;
let decoded = func.decode_output(res.as_ref())?;
// handle case when return type is not specified
if decoded.is_empty() {
Ok(format!("{}\n", res))
} else {
// concatenate them
let mut s = String::new();
for output in decoded {
s.push_str(&format!("0x{}\n", output));
}

// concatenate them
let mut s = String::new();
for output in res {
s.push_str(&format!("{}\n", output));
// return string
Ok(s)
}

// return string
Ok(s)
}

pub async fn balance<T: Into<NameOrAddress> + Send + Sync>(
Expand Down Expand Up @@ -308,6 +312,46 @@ where
) -> Result<String> {
Ok(format!("{}", self.provider.get_code(who, block).await?))
}

/// ```no_run
/// use cast::Cast;
/// use ethers_providers::{Provider, Http};
/// use std::convert::TryFrom;
///
/// # async fn foo() -> eyre::Result<()> {
/// let provider = Provider::<Http>::try_from("http://localhost:8545")?;
/// let cast = Cast::new(provider);
/// let tx_hash = "0xf8d1713ea15a81482958fb7ddf884baee8d3bcc478c5f2f604e008dc788ee4fc";
/// let tx = cast.transaction(tx_hash.to_string(), None, false).await?;
/// println!("{}", tx);
/// # Ok(())
/// # }
/// ```
pub async fn transaction(
&self,
tx_hash: String,
field: Option<String>,
to_json: bool,
) -> Result<String> {
let transaction_result = self
.provider
.get_transaction(H256::from_str(&tx_hash)?)
.await?
.ok_or_else(|| eyre::eyre!("transaction {:?} not found", tx_hash))?;

let transaction = if let Some(ref field) = field {
serde_json::to_value(&transaction_result)?
.get(field)
.cloned()
.ok_or_else(|| eyre::eyre!("field {} not found", field))?
} else {
serde_json::to_value(&transaction_result)?
};

let transaction =
if to_json { serde_json::to_string(&transaction)? } else { to_table(transaction) };
Ok(transaction)
}
}

pub struct SimpleCast;
Expand Down Expand Up @@ -471,6 +515,41 @@ impl SimpleCast {
})
}

/// Converts wei into an eth amount
///
/// ```
/// use cast::SimpleCast as Cast;
///
/// fn main() -> eyre::Result<()> {
/// assert_eq!(Cast::from_wei(1.into(), "gwei".to_string())?, "0.000000001");
/// assert_eq!(Cast::from_wei(12340000005u64.into(), "gwei".to_string())?, "12.340000005");
/// assert_eq!(Cast::from_wei(10.into(), "ether".to_string())?, "0.00000000000000001");
/// assert_eq!(Cast::from_wei(100.into(), "eth".to_string())?, "0.0000000000000001");
/// assert_eq!(Cast::from_wei(17.into(), "".to_string())?, "17");
///
/// Ok(())
/// }
/// ```
pub fn from_wei(value: U256, unit: String) -> Result<String> {
Ok(match &unit[..] {
"gwei" => {
let gwei = U256::pow(10.into(), 9.into());
let left = value / gwei;
let right = value - left * gwei;
let res = format!("{}.{:0>9}", left, right.to_string());
res.trim_end_matches('0').to_string()
}
"eth" | "ether" => {
let wei = U256::pow(10.into(), 18.into());
let left = value / wei;
let right = value - left * wei;
let res = format!("{}.{:0>18}", left, right.to_string());
res.trim_end_matches('0').to_string()
}
_ => value.to_string(),
})
}

/// Converts an Ethereum address to its checksum format
/// according to [EIP-55](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md)
///
Expand Down
14 changes: 14 additions & 0 deletions cli/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ async fn main() -> eyre::Result<()> {
)?
);
}
Subcommands::FromWei { value, unit } => {
let val = unwrap_or_stdin(value)?;
println!(
"{}",
SimpleCast::from_wei(
U256::from_dec_str(&val)?,
unit.unwrap_or_else(|| String::from("wei"))
)?
);
}
Subcommands::Block { rpc_url, block, full, field, to_json } => {
let provider = Provider::try_from(rpc_url)?;
println!("{}", Cast::new(provider).block(block, full, field, to_json).await?);
Expand Down Expand Up @@ -124,6 +134,10 @@ async fn main() -> eyre::Result<()> {
Subcommands::Namehash { name } => {
println!("{}", SimpleCast::namehash(&name)?);
}
Subcommands::Tx { rpc_url, hash, field, to_json } => {
let provider = Provider::try_from(rpc_url)?;
println!("{}", Cast::new(&provider).transaction(hash, field, to_json).await?)
}
Subcommands::SendTx { eth, to, sig, cast_async, args } => {
let provider = Provider::try_from(eth.rpc_url.as_str())?;
let chain_id = Cast::new(&provider).chain_id().await?;
Expand Down
26 changes: 19 additions & 7 deletions cli/src/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

use ethers::{
solc::{
artifacts::Settings, remappings::Remapping, EvmVersion, MinimalCombinedArtifacts, Project,
ProjectCompileOutput, ProjectPathsConfig, SolcConfig,
artifacts::{Optimizer, Settings},
remappings::Remapping,
EvmVersion, MinimalCombinedArtifacts, Project, ProjectCompileOutput, ProjectPathsConfig,
SolcConfig,
},
types::Address,
};
Expand All @@ -29,7 +31,7 @@ pub struct BuildArgs {
pub root: Option<PathBuf>,

#[structopt(
help = "the directory relative to the root under which the smart contrats are",
help = "the directory relative to the root under which the smart contracts are",
long,
short
)]
Expand All @@ -50,6 +52,12 @@ pub struct BuildArgs {
#[structopt(help = "choose the evm version", long, default_value = "london")]
pub evm_version: EvmVersion,

#[structopt(help = "activate the solidity optimizer", long)]
pub optimize: bool,

#[structopt(help = "optimizer parameter runs", long, default_value = "200")]
pub optimize_runs: u32,

#[structopt(
help = "if set to true, skips auto-detecting solc and uses what is in the user's $PATH ",
long
Expand All @@ -65,7 +73,8 @@ pub struct BuildArgs {
#[structopt(
help = "uses hardhat style project layout. This a convenience flag and is the same as `--contracts contracts --lib-paths node_modules`",
long,
conflicts_with = "contracts"
conflicts_with = "contracts",
alias = "hh"
)]
pub hardhat: bool,
}
Expand Down Expand Up @@ -156,8 +165,7 @@ impl BuildArgs {
let lib_paths = self.libs(&root);

// get all the remappings corresponding to the lib paths
let mut remappings: Vec<_> =
lib_paths.iter().flat_map(|path| Remapping::find_many(&path).unwrap()).collect();
let mut remappings: Vec<_> = lib_paths.iter().flat_map(Remapping::find_many).collect();

// extend them with the once manually provided in the opts
remappings.extend_from_slice(&self.remappings);
Expand Down Expand Up @@ -194,8 +202,12 @@ impl BuildArgs {

let paths = paths_builder.build()?;

let optimizer =
Optimizer { enabled: Some(self.optimize), runs: Some(self.optimize_runs as usize) };

// build the project w/ allowed paths = root and all the libs
let solc_settings = Settings { evm_version: Some(self.evm_version), ..Default::default() };
let solc_settings =
Settings { optimizer, evm_version: Some(self.evm_version), ..Default::default() };
let mut builder = Project::builder()
.paths(paths)
.allowed_path(&root)
Expand Down
1 change: 0 additions & 1 deletion cli/src/cmd/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ pub struct TestArgs {
short
)]
#[structopt(alias = "rpc-url")]
#[structopt(env = "ETH_RPC_URL")]
fork_url: Option<String>,

#[structopt(help = "pins the block number for the state fork", long)]
Expand Down
16 changes: 7 additions & 9 deletions cli/src/forge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ fn main() -> eyre::Result<()> {
let root = std::fs::canonicalize(root)?;

let lib_paths = if lib_paths.is_empty() { vec![root.join("lib")] } else { lib_paths };
let remappings: Vec<_> =
lib_paths.iter().flat_map(|path| Remapping::find_many(&path).unwrap()).collect();
let remappings: Vec<_> = lib_paths.iter().flat_map(Remapping::find_many).collect();
remappings.iter().for_each(|x| println!("{}", x));
}
Subcommands::Init { root, template } => {
Expand Down Expand Up @@ -105,14 +104,13 @@ fn main() -> eyre::Result<()> {
.wait()?;
if !is_git.success() {
Command::new("git").arg("init").current_dir(&root).spawn()?.wait()?;
Command::new("git").args(&["add", "."]).current_dir(&root).spawn()?.wait()?;
Command::new("git")
.args(&["commit", "-m", "chore: forge init"])
.current_dir(&root)
.spawn()?
.wait()?;
}
Command::new("git").args(&["add", "."]).current_dir(&root).spawn()?.wait()?;
Command::new("git")
.args(&["commit", "-m", "chore: forge init"])
.current_dir(&root)
.spawn()?
.wait()?;

Dependency::from_str("https://github.com/dapphub/ds-test")
.and_then(|dependency| install(root, vec![dependency]))?;
}
Expand Down
13 changes: 13 additions & 0 deletions cli/src/opts/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ pub enum Subcommands {
#[structopt(name = "--to-wei")]
#[structopt(about = "convert an ETH amount into wei")]
ToWei { value: Option<String>, unit: Option<String> },
#[structopt(name = "--from-wei")]
#[structopt(about = "convert wei into an ETH amount")]
FromWei { value: Option<String>, unit: Option<String> },
#[structopt(name = "block")]
#[structopt(
about = "Prints information about <block>. If <field> is given, print only the value of that field"
Expand Down Expand Up @@ -107,6 +110,16 @@ pub enum Subcommands {
#[structopt(name = "namehash")]
#[structopt(about = "returns ENS namehash of provided name")]
Namehash { name: String },
#[structopt(name = "tx")]
#[structopt(about = "Show information about the transaction <tx-hash>")]
Tx {
hash: String,
field: Option<String>,
#[structopt(long = "--json", short = "-j")]
to_json: bool,
#[structopt(long, env = "ETH_RPC_URL")]
rpc_url: String,
},
#[structopt(name = "send")]
#[structopt(about = "Publish a transaction signed by <from> to call <to> with <data>")]
SendTx {
Expand Down
4 changes: 4 additions & 0 deletions evm-adapters/src/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ impl FuzzedCases {

/// Returns the average gas use of all test cases
pub fn mean_gas(&self) -> u64 {
if self.cases.is_empty() {
return 0
}

(self.cases.iter().map(|c| c.gas as u128).sum::<u128>() / self.cases.len() as u128) as u64
}

Expand Down
Loading

0 comments on commit daebf1b

Please sign in to comment.