feat(solc): better metadata support (#894)
This commit is contained in:
parent
0a5b0d3495
commit
8aeeaa83b0
|
@ -103,9 +103,14 @@ impl Default for CompilerInput {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Settings {
|
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")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
pub remappings: Vec<Remapping>,
|
pub remappings: Vec<Remapping>,
|
||||||
pub optimizer: Optimizer,
|
pub optimizer: Optimizer,
|
||||||
|
/// Metadata settings
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub metadata: Option<SettingsMetadata>,
|
pub metadata: Option<SettingsMetadata>,
|
||||||
/// This field can be used to select desired outputs based
|
/// This field can be used to select desired outputs based
|
||||||
|
@ -199,6 +204,50 @@ impl Settings {
|
||||||
output_selection
|
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
|
/// Adds `ast` to output
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_ast(mut self) -> Self {
|
pub fn with_ast(mut self) -> Self {
|
||||||
|
@ -211,6 +260,7 @@ impl Settings {
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
stop_after: None,
|
||||||
optimizer: Default::default(),
|
optimizer: Default::default(),
|
||||||
metadata: None,
|
metadata: None,
|
||||||
output_selection: Self::default_output_selection(),
|
output_selection: Self::default_output_selection(),
|
||||||
|
@ -392,26 +442,60 @@ impl FromStr for EvmVersion {
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SettingsMetadata {
|
pub struct SettingsMetadata {
|
||||||
|
/// Use only literal content and not URLs (false by default)
|
||||||
#[serde(default, rename = "useLiteralContent", skip_serializing_if = "Option::is_none")]
|
#[serde(default, rename = "useLiteralContent", skip_serializing_if = "Option::is_none")]
|
||||||
pub use_literal_content: Option<bool>,
|
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")]
|
#[serde(default, rename = "bytecodeHash", skip_serializing_if = "Option::is_none")]
|
||||||
pub bytecode_hash: Option<String>,
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
pub compiler: Compiler,
|
pub compiler: Compiler,
|
||||||
pub language: String,
|
pub language: String,
|
||||||
pub output: Output,
|
pub output: Output,
|
||||||
pub settings: Settings,
|
pub settings: MetadataSettings,
|
||||||
pub sources: MetadataSources,
|
pub sources: MetadataSources,
|
||||||
pub version: i64,
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MetadataSources {
|
pub struct MetadataSources {
|
||||||
#[serde(flatten)]
|
#[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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
|
|
@ -726,6 +726,17 @@ mod tests {
|
||||||
assert_eq!(out, other);
|
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")]
|
#[cfg(feature = "async")]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn async_solc_compile_works() {
|
async fn async_solc_compile_works() {
|
||||||
|
|
Loading…
Reference in New Issue