Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(solc): better metadata support
Browse files Browse the repository at this point in the history
mattsse committed Feb 10, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 0a5b0d3 commit 6f8cc45
Showing 2 changed files with 97 additions and 2 deletions.
88 changes: 86 additions & 2 deletions ethers-solc/src/artifacts.rs
Original file line number Diff line number Diff line change
@@ -103,9 +103,14 @@ impl Default for CompilerInput {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Settings {
/// Stop compilation after the given stage.
/// since 0.8.11: only "parsing" is valid here
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stop_after: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub remappings: Vec<Remapping>,
pub optimizer: Optimizer,
/// Metadata settings
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<SettingsMetadata>,
/// This field can be used to select desired outputs based
@@ -199,6 +204,50 @@ impl Settings {
output_selection
}

/// Inserts the value for all files and contracts
pub fn push_output_selection(&mut self, value: impl Into<String>) {
self.push_contract_output_selection("*", value)
}

/// Inserts the `key` `value` pair to the `output_selection` for all files
///
/// If the `key` already exists, then the value is added to the existing list
pub fn push_contract_output_selection(
&mut self,
contracts: impl Into<String>,
value: impl Into<String>,
) {
let value = value.into();
let values = self
.output_selection
.entry("*".to_string())
.or_default()
.entry(contracts.into())
.or_default();
if !values.contains(&value) {
values.push(value)
}
}

/// Sets the value for all files and contracts
pub fn set_output_selection(&mut self, values: impl IntoIterator<Item = impl Into<String>>) {
self.set_contract_output_selection("*", values)
}

/// Sets the `key` to the `values` pair to the `output_selection` for all files
///
/// This will replace the existing values for `key` if they're present
pub fn set_contract_output_selection(
&mut self,
key: impl Into<String>,
values: impl IntoIterator<Item = impl Into<String>>,
) {
self.output_selection
.entry("*".to_string())
.or_default()
.insert(key.into(), values.into_iter().map(Into::into).collect());
}

/// Adds `ast` to output
#[must_use]
pub fn with_ast(mut self) -> Self {
@@ -211,6 +260,7 @@ impl Settings {
impl Default for Settings {
fn default() -> Self {
Self {
stop_after: None,
optimizer: Default::default(),
metadata: None,
output_selection: Self::default_output_selection(),
@@ -392,26 +442,60 @@ impl FromStr for EvmVersion {
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct SettingsMetadata {
/// Use only literal content and not URLs (false by default)
#[serde(default, rename = "useLiteralContent", skip_serializing_if = "Option::is_none")]
pub use_literal_content: Option<bool>,
/// Use the given hash method for the metadata hash that is appended to the bytecode.
/// The metadata hash can be removed from the bytecode via option "none".
/// The other options are "ipfs" and "bzzr1".
/// If the option is omitted, "ipfs" is used by default.
#[serde(default, rename = "bytecodeHash", skip_serializing_if = "Option::is_none")]
pub bytecode_hash: Option<String>,
}

/// Bindings for [`solc` contract metadata](https://docs.soliditylang.org/en/latest/metadata.html)
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Metadata {
pub compiler: Compiler,
pub language: String,
pub output: Output,
pub settings: Settings,
pub settings: MetadataSettings,
pub sources: MetadataSources,
pub version: i64,
}

/// Compiler settings
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MetadataSettings {
/// Required for Solidity: File and name of the contract or library this metadata is created
/// for.
#[serde(default, rename = "compilationTarget")]
pub compilation_target: BTreeMap<String, String>,
#[serde(flatten)]
pub inner: Settings,
}

/// Compilation source files/source units, keys are file names
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct MetadataSources {
#[serde(flatten)]
pub inner: BTreeMap<String, serde_json::Value>,
pub inner: BTreeMap<String, MetadataSource>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MetadataSource {
/// Required: keccak256 hash of the source file
pub keccak256: String,
/// Required (unless "content" is used, see below): Sorted URL(s)
/// to the source file, protocol is more or less arbitrary, but a
/// Swarm URL is recommended
#[serde(default)]
pub urls: Vec<String>,
/// Required (unless "url" is used): literal contents of the source file
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
/// Optional: SPDX license identifier as given in the source file
pub license: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
11 changes: 11 additions & 0 deletions ethers-solc/src/compile/mod.rs
Original file line number Diff line number Diff line change
@@ -726,6 +726,17 @@ mod tests {
assert_eq!(out, other);
}

#[test]
fn solc_metadata_works() {
let input = include_str!("../../test-data/in/compiler-in-1.json");
let mut input: CompilerInput = serde_json::from_str(input).unwrap();
input.settings.push_output_selection("metadata");
let out = solc().compile(&input).unwrap();
for (_, c) in out.split().1.contracts_iter() {
assert!(c.metadata.is_some());
}
}

#[cfg(feature = "async")]
#[tokio::test]
async fn async_solc_compile_works() {

0 comments on commit 6f8cc45

Please sign in to comment.