mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 18:01:05 +00:00
157 lines
5.1 KiB
Rust
157 lines
5.1 KiB
Rust
//! The Solidity contract build.
|
|
|
|
use std::collections::HashSet;
|
|
use std::fs::File;
|
|
use std::io::Write;
|
|
use std::path::Path;
|
|
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
|
|
use crate::solc::combined_json::contract::Contract as CombinedJsonContract;
|
|
use crate::solc::standard_json::output::contract::Contract as StandardJsonOutputContract;
|
|
|
|
/// The Solidity contract build.
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Contract {
|
|
/// The contract path.
|
|
pub path: String,
|
|
/// The auxiliary identifier. Used to identify Yul objects.
|
|
pub identifier: String,
|
|
/// The LLVM module build.
|
|
pub build: revive_llvm_context::PolkaVMBuild,
|
|
/// The metadata JSON.
|
|
pub metadata_json: serde_json::Value,
|
|
/// The factory dependencies.
|
|
pub factory_dependencies: HashSet<String>,
|
|
}
|
|
|
|
impl Contract {
|
|
/// A shortcut constructor.
|
|
pub fn new(
|
|
path: String,
|
|
identifier: String,
|
|
build: revive_llvm_context::PolkaVMBuild,
|
|
metadata_json: serde_json::Value,
|
|
factory_dependencies: HashSet<String>,
|
|
) -> Self {
|
|
Self {
|
|
path,
|
|
identifier,
|
|
build,
|
|
metadata_json,
|
|
factory_dependencies,
|
|
}
|
|
}
|
|
|
|
/// Writes the contract text assembly and bytecode to files.
|
|
pub fn write_to_directory(
|
|
self,
|
|
path: &Path,
|
|
output_assembly: bool,
|
|
output_binary: bool,
|
|
overwrite: bool,
|
|
) -> anyhow::Result<()> {
|
|
let file_name = Self::short_path(self.path.as_str());
|
|
|
|
if output_assembly {
|
|
let file_name = format!(
|
|
"{}.{}",
|
|
file_name,
|
|
revive_common::EXTENSION_POLKAVM_ASSEMBLY
|
|
);
|
|
let mut file_path = path.to_owned();
|
|
file_path.push(file_name);
|
|
|
|
if file_path.exists() && !overwrite {
|
|
anyhow::bail!(
|
|
"Refusing to overwrite an existing file {file_path:?} (use --overwrite to force)."
|
|
);
|
|
} else {
|
|
let assembly_text = self.build.assembly_text;
|
|
|
|
File::create(&file_path)
|
|
.map_err(|error| {
|
|
anyhow::anyhow!("File {:?} creating error: {}", file_path, error)
|
|
})?
|
|
.write_all(assembly_text.as_bytes())
|
|
.map_err(|error| {
|
|
anyhow::anyhow!("File {:?} writing error: {}", file_path, error)
|
|
})?;
|
|
}
|
|
}
|
|
|
|
if output_binary {
|
|
let file_name = format!("{}.{}", file_name, revive_common::EXTENSION_POLKAVM_BINARY);
|
|
let mut file_path = path.to_owned();
|
|
file_path.push(file_name);
|
|
|
|
if file_path.exists() && !overwrite {
|
|
anyhow::bail!(
|
|
"Refusing to overwrite an existing file {file_path:?} (use --overwrite to force)."
|
|
);
|
|
} else {
|
|
File::create(&file_path)
|
|
.map_err(|error| {
|
|
anyhow::anyhow!("File {:?} creating error: {}", file_path, error)
|
|
})?
|
|
.write_all(self.build.bytecode.as_slice())
|
|
.map_err(|error| {
|
|
anyhow::anyhow!("File {:?} writing error: {}", file_path, error)
|
|
})?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Writes the contract text assembly and bytecode to the combined JSON.
|
|
pub fn write_to_combined_json(
|
|
self,
|
|
combined_json_contract: &mut CombinedJsonContract,
|
|
) -> anyhow::Result<()> {
|
|
if let Some(metadata) = combined_json_contract.metadata.as_mut() {
|
|
*metadata = self.metadata_json.to_string();
|
|
}
|
|
|
|
if let Some(asm) = combined_json_contract.asm.as_mut() {
|
|
*asm = serde_json::Value::String(self.build.assembly_text);
|
|
}
|
|
let hexadecimal_bytecode = hex::encode(self.build.bytecode);
|
|
combined_json_contract.bin = Some(hexadecimal_bytecode);
|
|
combined_json_contract
|
|
.bin_runtime
|
|
.clone_from(&combined_json_contract.bin);
|
|
|
|
combined_json_contract.factory_deps = Some(self.build.factory_dependencies);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Writes the contract text assembly and bytecode to the standard JSON.
|
|
pub fn write_to_standard_json(
|
|
self,
|
|
standard_json_contract: &mut StandardJsonOutputContract,
|
|
) -> anyhow::Result<()> {
|
|
standard_json_contract.metadata = Some(self.metadata_json);
|
|
|
|
let assembly_text = self.build.assembly_text;
|
|
let bytecode = hex::encode(self.build.bytecode.as_slice());
|
|
if let Some(evm) = standard_json_contract.evm.as_mut() {
|
|
evm.modify(assembly_text, bytecode);
|
|
}
|
|
|
|
standard_json_contract.factory_dependencies = Some(self.build.factory_dependencies);
|
|
standard_json_contract.hash = Some(self.build.bytecode_hash);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Converts the full path to a short one.
|
|
pub fn short_path(path: &str) -> &str {
|
|
path.rfind('/')
|
|
.map(|last_slash| &path[last_slash + 1..])
|
|
.unwrap_or_else(|| path)
|
|
}
|
|
}
|