diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index e523c3813c58..6e9de9791110 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -23,6 +23,42 @@ use std::{ const CALL_PROTECTION_BYTECODE_PREFIX: [u8; 21] = hex!("730000000000000000000000000000000000000000"); +/// Subset of [CompactBytecode] excluding sourcemaps. +#[allow(missing_docs)] +#[derive(Debug, Clone)] +pub struct BytecodeData { + pub object: Option, + pub link_references: BTreeMap>>, + pub immutable_references: BTreeMap>, +} + +impl BytecodeData { + fn bytes(&self) -> Option<&Bytes> { + self.object.as_ref().and_then(|b| b.as_bytes()) + } +} + +impl From for BytecodeData { + fn from(bytecode: CompactBytecode) -> Self { + Self { + object: Some(bytecode.object), + link_references: bytecode.link_references, + immutable_references: BTreeMap::new(), + } + } +} + +impl From for BytecodeData { + fn from(bytecode: CompactDeployedBytecode) -> Self { + let (object, link_references) = if let Some(compact) = bytecode.bytecode { + (Some(compact.object), compact.link_references) + } else { + (None, BTreeMap::new()) + }; + Self { object, link_references, immutable_references: bytecode.immutable_references } + } +} + /// Container for commonly used contract data. #[derive(Debug, Clone)] pub struct ContractData { @@ -31,9 +67,9 @@ pub struct ContractData { /// Contract ABI. pub abi: JsonAbi, /// Contract creation code. - pub bytecode: Option, + pub bytecode: Option, /// Contract runtime code. - pub deployed_bytecode: Option, + pub deployed_bytecode: Option, } impl ContractData { @@ -68,7 +104,15 @@ impl ContractsByArtifact { let CompactContractBytecode { abi, bytecode, deployed_bytecode } = artifact; - Some((id, ContractData { name, abi: abi?, bytecode, deployed_bytecode })) + Some(( + id, + ContractData { + name, + abi: abi?, + bytecode: bytecode.map(Into::into), + deployed_bytecode: deployed_bytecode.map(Into::into), + }, + )) }) .collect(), ) @@ -103,11 +147,11 @@ impl ContractsByArtifact { let Some(deployed_bytecode) = &contract.deployed_bytecode else { return false; }; - let Some(deployed_code) = &deployed_bytecode.bytecode else { + let Some(deployed_code) = &deployed_bytecode.object else { return false; }; - let len = match deployed_code.object { + let len = match deployed_code { BytecodeObject::Bytecode(ref bytes) => bytes.len(), BytecodeObject::Unlinked(ref bytes) => bytes.len() / 2, }; @@ -120,7 +164,7 @@ impl ContractsByArtifact { let mut ignored = deployed_bytecode .immutable_references .values() - .chain(deployed_code.link_references.values().flat_map(|v| v.values())) + .chain(deployed_bytecode.link_references.values().flat_map(|v| v.values())) .flatten() .cloned() .collect::>(); @@ -129,7 +173,7 @@ impl ContractsByArtifact { // ignore it as it includes library address determined at runtime. // See https://docs.soliditylang.org/en/latest/contracts.html#call-protection-for-libraries and // https://github.com/NomicFoundation/hardhat/blob/af7807cf38842a4f56e7f4b966b806e39631568a/packages/hardhat-verify/src/internal/solc/bytecode.ts#L172 - let has_call_protection = match deployed_code.object { + let has_call_protection = match deployed_code { BytecodeObject::Bytecode(ref bytes) => { bytes.starts_with(&CALL_PROTECTION_BYTECODE_PREFIX) } @@ -154,7 +198,7 @@ impl ContractsByArtifact { for offset in ignored { let right = offset.start as usize; - let matched = match deployed_code.object { + let matched = match deployed_code { BytecodeObject::Bytecode(ref bytes) => bytes[left..right] == code[left..right], BytecodeObject::Unlinked(ref bytes) => { if let Ok(bytes) = Bytes::from_str(&bytes[left * 2..right * 2]) { @@ -173,7 +217,7 @@ impl ContractsByArtifact { } if left < code.len() { - match deployed_code.object { + match deployed_code { BytecodeObject::Bytecode(ref bytes) => bytes[left..] == code[left..], BytecodeObject::Unlinked(ref bytes) => { if let Ok(bytes) = Bytes::from_str(&bytes[left * 2..]) {