diff --git a/Cargo.lock b/Cargo.lock index 24dec85d..c0ba7fee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -805,8 +805,7 @@ dependencies = [ [[package]] name = "ethabi" version = "14.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01317735d563b3bad2d5f90d2e1799f414165408251abb762510f40e790e69a" +source = "git+https://github.com/rust-ethereum/ethabi/?branch=master#506f6cc364cdb458ac09f2be4f300779da256b08" dependencies = [ "anyhow", "ethereum-types", @@ -833,9 +832,9 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64b5df66a228d85e4b17e5d6c6aa43b0310898ffe8a85988c4c032357aaabfd" +checksum = "0dd6bde671199089e601e8d47e153368b893ef885f11f365a3261ec58153c211" dependencies = [ "ethbloom", "fixed-hash", @@ -1946,9 +1945,9 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "primitive-types" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06345ee39fbccfb06ab45f3a1a5798d9dafa04cb8921a76d227040003a234b0e" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-codec", diff --git a/Cargo.toml b/Cargo.toml index 200eb605..8463a5a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,3 +86,4 @@ rand = "0.8.4" serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0.64" tokio = { version = "1.5", features = ["macros", "rt-multi-thread"] } + diff --git a/ethers-contract/ethers-contract-derive/src/abigen.rs b/ethers-contract/ethers-contract-derive/src/abigen.rs index ac718a88..f0cfc2e3 100644 --- a/ethers-contract/ethers-contract-derive/src/abigen.rs +++ b/ethers-contract/ethers-contract-derive/src/abigen.rs @@ -169,6 +169,7 @@ impl Parse for Method { Ok(Param { name: "".into(), kind, + internal_type: None, }) }) .collect::>>()?; diff --git a/ethers-core/Cargo.toml b/ethers-core/Cargo.toml index 726add54..0ed84d52 100644 --- a/ethers-core/Cargo.toml +++ b/ethers-core/Cargo.toml @@ -11,7 +11,8 @@ keywords = ["ethereum", "web3", "celo", "ethers"] [dependencies] rlp = { version = "0.5.0", default-features = false } -ethabi = { version = "14.1.0", default-features = false } +# ethabi = { version = "14.1.0", default-features = false } +ethabi = { git = "https://github.com/rust-ethereum/ethabi/", branch = "master" } arrayvec = { version = "0.7.1", default-features = false } rlp-derive = { version = "0.1.0", default-features = false } diff --git a/ethers-core/src/abi/human_readable.rs b/ethers-core/src/abi/human_readable.rs index 2a08fc5b..11f41a63 100644 --- a/ethers-core/src/abi/human_readable.rs +++ b/ethers-core/src/abi/human_readable.rs @@ -364,6 +364,7 @@ impl AbiParser { Ok(Param { name: name.to_string(), kind: self.parse_type(type_str)?, + internal_type: None, }) } } diff --git a/ethers-core/src/utils/solc.rs b/ethers-core/src/utils/solc.rs index da4692e7..9c36e1ec 100644 --- a/ethers-core/src/utils/solc.rs +++ b/ethers-core/src/utils/solc.rs @@ -21,13 +21,15 @@ pub enum SolcError { SerdeJson(#[from] serde_json::Error), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] /// The result of a solc compilation pub struct CompiledContract { /// The contract's ABI pub abi: Abi, /// The contract's bytecode pub bytecode: Bytes, + /// The contract's runtime bytecode + pub runtime_bytecode: Bytes, } /// Solidity Compiler Bindings @@ -55,6 +57,9 @@ pub struct CompiledContract { /// # } /// ``` pub struct Solc { + /// The path to the Solc binary + pub solc_path: Option, + /// The path where contracts will be read from pub paths: Vec, @@ -72,7 +77,7 @@ pub struct Solc { } impl Solc { - /// Instantiates the Solc builder for the provided paths + /// Instantiates The Solc builder with the provided glob of Solidity files pub fn new(path: &str) -> Self { // Convert the glob to a vector of string paths // TODO: This might not be the most robust way to do this @@ -80,9 +85,14 @@ impl Solc { .expect("could not get glob") .map(|path| path.expect("path not found").to_string_lossy().to_string()) .collect::>(); + Self::new_with_paths(paths) + } + /// Instantiates the Solc builder for the provided paths + pub fn new_with_paths(paths: Vec) -> Self { Self { paths, + solc_path: None, optimizer: Some(200), // default optimizer runs = 200 evm_version: EvmVersion::Istanbul, allowed_paths: Vec::new(), @@ -92,13 +102,19 @@ impl Solc { /// Gets the ABI for the contracts pub fn build_raw(self) -> Result> { - let mut command = Command::new(SOLC); + let path = self.solc_path.unwrap_or_else(|| PathBuf::from(SOLC)); + let mut command = Command::new(&path); + let version = Solc::version(Some(path)); - command - .arg("--evm-version") - .arg(self.evm_version.to_string()) - .arg("--combined-json") - .arg("abi,bin"); + command.arg("--combined-json").arg("abi,bin,bin-runtime"); + + if (version.starts_with("0.5") && self.evm_version < EvmVersion::Istanbul) + || !version.starts_with("0.4") + { + command + .arg("--evm-version") + .arg(self.evm_version.to_string()); + } if let Some(runs) = self.optimizer { command @@ -148,7 +164,21 @@ impl Solc { ))) } }; - contracts.insert(name, CompiledContractStr { abi, bin }); + + let runtime_bin = + if let serde_json::Value::String(bin) = contract["bin-runtime"].take() { + bin + } else { + panic!("no runtime bytecode found") + }; + contracts.insert( + name, + CompiledContractStr { + abi, + bin, + runtime_bin, + }, + ); } else { return Err(SolcError::SolcError( "could not find `bin` in solc output".to_string(), @@ -174,7 +204,19 @@ impl Solc { let bytecode = hex::decode(contract.bin) .expect("solc did not produce valid bytecode") .into(); - (name, CompiledContract { abi, bytecode }) + + // parse the runtime bytecode + let runtime_bytecode = hex::decode(contract.runtime_bin) + .expect("solc did not produce valid runtime-bytecode") + .into(); + ( + name, + CompiledContract { + abi, + bytecode, + runtime_bytecode, + }, + ) }) .collect::>(); @@ -186,8 +228,8 @@ impl Solc { /// # Panics /// /// If `solc` is not in the user's $PATH - pub fn version() -> String { - let command_output = Command::new(SOLC) + pub fn version(solc_path: Option) -> String { + let command_output = Command::new(solc_path.unwrap_or_else(|| PathBuf::from(SOLC))) .arg("--version") .output() .unwrap_or_else(|_| panic!("`{}` not in user's $PATH", SOLC)); @@ -209,6 +251,12 @@ impl Solc { self } + /// Sets the path to the solc binary + pub fn solc_path(mut self, path: PathBuf) -> Self { + self.solc_path = Some(std::fs::canonicalize(path).unwrap()); + self + } + /// Sets the optimizer runs (default = 200). None indicates no optimization /// /// ```rust,no_run @@ -257,7 +305,7 @@ impl Solc { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum EvmVersion { Homestead, TangerineWhistle, @@ -297,4 +345,6 @@ pub struct CompiledContractStr { pub abi: String, /// The contract's bytecode in hex pub bin: String, + /// The contract's runtime bytecode in hex + pub runtime_bin: String, }