1use crate::{
12 sources::VersionedSourceFile, Artifact, ArtifactFile, ArtifactOutput, SolcConfig, SolcError,
13 SourceFile,
14};
15use alloy_json_abi::JsonAbi;
16use alloy_primitives::hex;
17use foundry_compilers_artifacts::{
18 bytecode::{CompactBytecode, CompactDeployedBytecode},
19 contract::Contract,
20 output_selection::{
21 BytecodeOutputSelection, ContractOutputSelection, DeployedBytecodeOutputSelection,
22 EvmOutputSelection, EwasmOutputSelection,
23 },
24 BytecodeObject, ConfigurableContractArtifact, Evm, Ewasm, GeneratedSource, LosslessMetadata,
25 Metadata, Settings,
26};
27use foundry_compilers_core::utils;
28use std::{fs, path::Path};
29
30#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
44pub struct ConfigurableArtifacts {
45 pub additional_values: ExtraOutputValues,
47
48 pub additional_files: ExtraOutputFiles,
50
51 #[doc(hidden)]
63 pub __non_exhaustive: (),
64}
65
66impl ConfigurableArtifacts {
67 pub fn new(
68 extra_values: impl IntoIterator<Item = ContractOutputSelection>,
69 extra_files: impl IntoIterator<Item = ContractOutputSelection>,
70 ) -> Self {
71 Self {
72 additional_values: ExtraOutputValues::from_output_selection(extra_values),
73 additional_files: ExtraOutputFiles::from_output_selection(extra_files),
74 ..Default::default()
75 }
76 }
77
78 pub fn solc_settings(&self) -> Settings {
80 SolcConfig::builder()
81 .additional_outputs(self.output_selection())
82 .ast(self.additional_values.ast)
83 .build()
84 }
85
86 pub fn output_selection(&self) -> Vec<ContractOutputSelection> {
88 let mut selection = ContractOutputSelection::basic();
89
90 let ExtraOutputValues {
91 ast: _,
93 userdoc,
94 devdoc,
95 method_identifiers,
96 storage_layout,
97 transient_storage_layout,
98 assembly,
99 legacy_assembly,
100 gas_estimates,
101 metadata,
102 ir,
103 ir_optimized,
104 ir_optimized_ast,
105 ewasm,
106 function_debug_data,
107 generated_sources,
108 source_map,
109 opcodes,
110 __non_exhaustive,
111 } = self.additional_values;
112
113 if ir || self.additional_files.ir {
114 selection.push(ContractOutputSelection::Ir);
115 }
116 if ir_optimized || self.additional_files.ir_optimized {
117 selection.push(ContractOutputSelection::IrOptimized);
118 }
119 if metadata || self.additional_files.metadata {
120 selection.push(ContractOutputSelection::Metadata);
121 }
122 if storage_layout {
123 selection.push(ContractOutputSelection::StorageLayout);
124 }
125 if devdoc {
126 selection.push(ContractOutputSelection::DevDoc);
127 }
128 if userdoc {
129 selection.push(ContractOutputSelection::UserDoc);
130 }
131 if gas_estimates {
132 selection.push(EvmOutputSelection::GasEstimates.into());
133 }
134 if assembly || self.additional_files.assembly {
135 selection.push(EvmOutputSelection::Assembly.into());
136 }
137 if legacy_assembly || self.additional_files.legacy_assembly {
138 selection.push(EvmOutputSelection::LegacyAssembly.into());
139 }
140 if ewasm || self.additional_files.ewasm {
141 selection.push(EwasmOutputSelection::All.into());
142 }
143 if function_debug_data {
144 selection.push(BytecodeOutputSelection::FunctionDebugData.into());
145 }
146 if method_identifiers {
147 selection.push(EvmOutputSelection::MethodIdentifiers.into());
148 }
149 if generated_sources {
150 selection.push(
151 EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources).into(),
152 );
153 }
154 if source_map {
155 selection.push(EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap).into());
156 }
157 if ir_optimized_ast {
158 selection.push(ContractOutputSelection::IrOptimizedAst);
159 }
160 if opcodes {
161 selection.push(EvmOutputSelection::ByteCode(BytecodeOutputSelection::Opcodes).into());
162 }
163 if transient_storage_layout {
164 selection.push(ContractOutputSelection::TransientStorageLayout);
165 }
166 selection
167 }
168}
169
170impl ArtifactOutput for ConfigurableArtifacts {
171 type Artifact = ConfigurableContractArtifact;
172 type CompilerContract = Contract;
173
174 fn handle_artifacts(
176 &self,
177 contracts: &crate::VersionedContracts<Contract>,
178 artifacts: &crate::Artifacts<Self::Artifact>,
179 ) -> Result<(), SolcError> {
180 for (file, contracts) in contracts.as_ref().iter() {
181 for (name, versioned_contracts) in contracts {
182 for contract in versioned_contracts {
183 if let Some(artifact) = artifacts.find_artifact(file, name, &contract.version) {
184 let file = &artifact.file;
185 utils::create_parent_dir_all(file)?;
186 self.additional_files.write_extras(&contract.contract, file)?;
187 }
188 }
189 }
190 }
191 Ok(())
192 }
193
194 fn contract_to_artifact(
195 &self,
196 _file: &Path,
197 _name: &str,
198 contract: Contract,
199 source_file: Option<&SourceFile>,
200 ) -> Self::Artifact {
201 let mut artifact_userdoc = None;
202 let mut artifact_devdoc = None;
203 let mut artifact_raw_metadata = None;
204 let mut artifact_metadata = None;
205 let mut artifact_ir = None;
206 let mut artifact_ir_optimized = None;
207 let mut artifact_ir_optimized_ast = None;
208 let mut artifact_ewasm = None;
209 let mut artifact_bytecode = None;
210 let mut artifact_deployed_bytecode = None;
211 let mut artifact_gas_estimates = None;
212 let mut artifact_function_debug_data = None;
213 let mut artifact_method_identifiers = None;
214 let mut artifact_assembly = None;
215 let mut artifact_legacy_assembly = None;
216 let mut artifact_storage_layout = None;
217 let mut artifact_transient_storage_layout = None;
218 let mut generated_sources = None;
219 let mut opcodes = None;
220
221 let Contract {
222 abi,
223 metadata,
224 userdoc,
225 devdoc,
226 ir,
227 storage_layout,
228 transient_storage_layout,
229 evm,
230 ewasm,
231 ir_optimized,
232 ir_optimized_ast,
233 } = contract;
234
235 if self.additional_values.metadata || self.additional_files.metadata {
236 if let Some(LosslessMetadata { raw_metadata, metadata }) = metadata {
237 artifact_raw_metadata = Some(raw_metadata);
238 artifact_metadata = Some(metadata);
239 }
240 }
241 if self.additional_values.userdoc {
242 artifact_userdoc = Some(userdoc);
243 }
244 if self.additional_values.devdoc {
245 artifact_devdoc = Some(devdoc);
246 }
247 if self.additional_values.ewasm || self.additional_files.ewasm {
248 artifact_ewasm = ewasm;
249 }
250 if self.additional_values.ir || self.additional_files.ir {
251 artifact_ir = ir;
252 }
253 if self.additional_values.ir_optimized || self.additional_files.ir_optimized {
254 artifact_ir_optimized = ir_optimized;
255 }
256 if self.additional_values.ir_optimized_ast {
257 artifact_ir_optimized_ast = ir_optimized_ast;
258 }
259 if self.additional_values.storage_layout {
260 artifact_storage_layout = Some(storage_layout);
261 }
262 if self.additional_values.transient_storage_layout {
263 artifact_transient_storage_layout = Some(transient_storage_layout);
264 }
265
266 if let Some(evm) = evm {
267 let Evm {
268 assembly,
269 mut bytecode,
270 deployed_bytecode,
271 method_identifiers,
272 gas_estimates,
273 legacy_assembly,
274 } = evm;
275
276 if self.additional_values.function_debug_data {
277 artifact_function_debug_data =
278 bytecode.as_mut().map(|code| std::mem::take(&mut code.function_debug_data));
279 }
280 if self.additional_values.generated_sources {
281 generated_sources =
282 bytecode.as_mut().map(|code| std::mem::take(&mut code.generated_sources));
283 }
284
285 if self.additional_values.opcodes {
286 opcodes = bytecode.as_mut().and_then(|code| code.opcodes.take())
287 }
288
289 artifact_bytecode = bytecode.map(Into::into);
290 artifact_deployed_bytecode = deployed_bytecode.map(Into::into);
291 artifact_method_identifiers = Some(method_identifiers);
292
293 if self.additional_values.gas_estimates {
294 artifact_gas_estimates = gas_estimates;
295 }
296 if self.additional_values.assembly || self.additional_files.assembly {
297 artifact_assembly = assembly;
298 }
299
300 if self.additional_values.legacy_assembly || self.additional_files.legacy_assembly {
301 artifact_legacy_assembly = legacy_assembly;
302 }
303 }
304
305 ConfigurableContractArtifact {
306 abi,
307 bytecode: artifact_bytecode,
308 deployed_bytecode: artifact_deployed_bytecode,
309 assembly: artifact_assembly,
310 legacy_assembly: artifact_legacy_assembly,
311 opcodes,
312 function_debug_data: artifact_function_debug_data,
313 method_identifiers: artifact_method_identifiers,
314 gas_estimates: artifact_gas_estimates,
315 raw_metadata: artifact_raw_metadata,
316 metadata: artifact_metadata,
317 storage_layout: artifact_storage_layout,
318 transient_storage_layout: artifact_transient_storage_layout,
319 userdoc: artifact_userdoc,
320 devdoc: artifact_devdoc,
321 ir: artifact_ir,
322 ir_optimized: artifact_ir_optimized,
323 ir_optimized_ast: artifact_ir_optimized_ast,
324 ewasm: artifact_ewasm,
325 id: source_file.as_ref().map(|s| s.id),
326 ast: source_file.and_then(|s| s.ast.clone()),
327 generated_sources: generated_sources.unwrap_or_default(),
328 }
329 }
330
331 fn standalone_source_file_to_artifact(
332 &self,
333 _path: &Path,
334 file: &VersionedSourceFile,
335 ) -> Option<Self::Artifact> {
336 file.source_file.ast.clone().map(|ast| ConfigurableContractArtifact {
337 abi: Some(JsonAbi::default()),
338 id: Some(file.source_file.id),
339 ast: Some(ast),
340 bytecode: Some(CompactBytecode::empty()),
341 deployed_bytecode: Some(CompactDeployedBytecode::empty()),
342 ..Default::default()
343 })
344 }
345
346 fn is_dirty(&self, artifact_file: &ArtifactFile<Self::Artifact>) -> Result<bool, SolcError> {
349 let artifact = &artifact_file.artifact;
350 let ExtraOutputFiles {
351 abi: _,
352 metadata,
353 ir,
354 ir_optimized,
355 ewasm,
356 assembly,
357 legacy_assembly,
358 source_map,
359 generated_sources,
360 bytecode: _,
361 deployed_bytecode: _,
362 __non_exhaustive: _,
363 } = self.additional_files;
364
365 if metadata && artifact.metadata.is_none() {
366 return Ok(true);
367 }
368 if ir && artifact.ir.is_none() {
369 return Ok(true);
370 }
371 if ir_optimized && artifact.ir_optimized.is_none() {
372 return Ok(true);
373 }
374 if ewasm && artifact.ewasm.is_none() {
375 return Ok(true);
376 }
377 if assembly && artifact.assembly.is_none() {
378 return Ok(true);
379 }
380 if legacy_assembly && artifact.legacy_assembly.is_none() {
381 return Ok(true);
382 }
383 if source_map && artifact.get_source_map_str().is_none() {
384 return Ok(true);
385 }
386 if generated_sources {
387 return Ok(true);
389 }
390 Ok(false)
391 }
392
393 fn handle_cached_artifacts(
395 &self,
396 artifacts: &crate::Artifacts<Self::Artifact>,
397 ) -> Result<(), SolcError> {
398 for artifacts in artifacts.values() {
399 for artifacts in artifacts.values() {
400 for artifact_file in artifacts {
401 let file = &artifact_file.file;
402 let artifact = &artifact_file.artifact;
403 self.additional_files.process_abi(artifact.abi.as_ref(), file)?;
404 self.additional_files.process_assembly(artifact.assembly.as_deref(), file)?;
405 self.additional_files
406 .process_legacy_assembly(artifact.legacy_assembly.clone(), file)?;
407 self.additional_files
408 .process_bytecode(artifact.bytecode.as_ref().map(|b| &b.object), file)?;
409 self.additional_files.process_deployed_bytecode(
410 artifact
411 .deployed_bytecode
412 .as_ref()
413 .and_then(|d| d.bytecode.as_ref())
414 .map(|b| &b.object),
415 file,
416 )?;
417 self.additional_files
418 .process_generated_sources(Some(&artifact.generated_sources), file)?;
419 self.additional_files.process_ir(artifact.ir.as_deref(), file)?;
420 self.additional_files
421 .process_ir_optimized(artifact.ir_optimized.as_deref(), file)?;
422 self.additional_files.process_ewasm(artifact.ewasm.as_ref(), file)?;
423 self.additional_files.process_metadata(artifact.metadata.as_ref(), file)?;
424 self.additional_files
425 .process_source_map(artifact.get_source_map_str().as_deref(), file)?;
426 }
427 }
428 }
429
430 Ok(())
431 }
432}
433
434#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
436pub struct ExtraOutputValues {
437 pub ast: bool,
438 pub userdoc: bool,
439 pub devdoc: bool,
440 pub method_identifiers: bool,
441 pub storage_layout: bool,
442 pub transient_storage_layout: bool,
443 pub assembly: bool,
444 pub legacy_assembly: bool,
445 pub gas_estimates: bool,
446 pub metadata: bool,
447 pub ir: bool,
448 pub ir_optimized: bool,
449 pub ir_optimized_ast: bool,
450 pub ewasm: bool,
451 pub function_debug_data: bool,
452 pub generated_sources: bool,
453 pub source_map: bool,
454 pub opcodes: bool,
455
456 #[doc(hidden)]
465 pub __non_exhaustive: (),
466}
467
468impl ExtraOutputValues {
469 pub fn all() -> Self {
471 Self {
472 ast: true,
473 userdoc: true,
474 devdoc: true,
475 method_identifiers: true,
476 storage_layout: true,
477 transient_storage_layout: true,
478 assembly: true,
479 legacy_assembly: true,
480 gas_estimates: true,
481 metadata: true,
482 ir: true,
483 ir_optimized: true,
484 ir_optimized_ast: true,
485 ewasm: true,
486 function_debug_data: true,
487 generated_sources: true,
488 source_map: true,
489 opcodes: true,
490 __non_exhaustive: (),
491 }
492 }
493
494 pub fn from_output_selection(
496 settings: impl IntoIterator<Item = ContractOutputSelection>,
497 ) -> Self {
498 let mut config = Self::default();
499 for value in settings.into_iter() {
500 match value {
501 ContractOutputSelection::DevDoc => {
502 config.devdoc = true;
503 }
504 ContractOutputSelection::UserDoc => {
505 config.userdoc = true;
506 }
507 ContractOutputSelection::Metadata => {
508 config.metadata = true;
509 }
510 ContractOutputSelection::Ir => {
511 config.ir = true;
512 }
513 ContractOutputSelection::IrOptimized => {
514 config.ir_optimized = true;
515 }
516 ContractOutputSelection::StorageLayout => {
517 config.storage_layout = true;
518 }
519 ContractOutputSelection::Evm(evm) => match evm {
520 EvmOutputSelection::All => {
521 config.assembly = true;
522 config.legacy_assembly = true;
523 config.gas_estimates = true;
524 config.method_identifiers = true;
525 config.generated_sources = true;
526 config.source_map = true;
527 config.opcodes = true;
528 }
529 EvmOutputSelection::Assembly => {
530 config.assembly = true;
531 }
532 EvmOutputSelection::LegacyAssembly => {
533 config.legacy_assembly = true;
534 }
535 EvmOutputSelection::MethodIdentifiers => {
536 config.method_identifiers = true;
537 }
538 EvmOutputSelection::GasEstimates => {
539 config.gas_estimates = true;
540 }
541 EvmOutputSelection::ByteCode(BytecodeOutputSelection::FunctionDebugData) => {
542 config.function_debug_data = true;
543 }
544 EvmOutputSelection::ByteCode(BytecodeOutputSelection::Opcodes) => {
545 config.opcodes = true;
546 }
547 EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources) => {
548 config.generated_sources = true;
549 }
550 EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap) => {
551 config.source_map = true;
552 }
553 _ => {}
554 },
555 ContractOutputSelection::Ewasm(_) => {
556 config.ewasm = true;
557 }
558 ContractOutputSelection::IrOptimizedAst => {
559 config.ir_optimized_ast = true;
560 }
561 ContractOutputSelection::TransientStorageLayout => {
562 config.transient_storage_layout = true;
563 }
564 ContractOutputSelection::Abi => {}
565 }
566 }
567
568 config
569 }
570}
571
572#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
574pub struct ExtraOutputFiles {
575 pub abi: bool,
576 pub metadata: bool,
577 pub ir: bool,
578 pub ir_optimized: bool,
579 pub ewasm: bool,
580 pub assembly: bool,
581 pub legacy_assembly: bool,
582 pub source_map: bool,
583 pub generated_sources: bool,
584 pub bytecode: bool,
585 pub deployed_bytecode: bool,
586
587 #[doc(hidden)]
596 pub __non_exhaustive: (),
597}
598
599impl ExtraOutputFiles {
600 pub fn all() -> Self {
602 Self {
603 abi: true,
604 metadata: true,
605 ir: true,
606 ir_optimized: true,
607 ewasm: true,
608 assembly: true,
609 legacy_assembly: true,
610 source_map: true,
611 generated_sources: true,
612 bytecode: true,
613 deployed_bytecode: true,
614 __non_exhaustive: (),
615 }
616 }
617
618 pub fn from_output_selection(
620 settings: impl IntoIterator<Item = ContractOutputSelection>,
621 ) -> Self {
622 let mut config = Self::default();
623 for value in settings.into_iter() {
624 match value {
625 ContractOutputSelection::Abi => {
626 config.abi = true;
627 }
628 ContractOutputSelection::Metadata => {
629 config.metadata = true;
630 }
631 ContractOutputSelection::Ir => {
632 config.ir = true;
633 }
634 ContractOutputSelection::IrOptimized => {
635 config.ir_optimized = true;
636 }
637 ContractOutputSelection::Evm(evm) => match evm {
638 EvmOutputSelection::All => {
639 config.assembly = true;
640 config.legacy_assembly = true;
641 config.generated_sources = true;
642 config.source_map = true;
643 config.bytecode = true;
644 config.deployed_bytecode = true;
645 }
646 EvmOutputSelection::Assembly => {
647 config.assembly = true;
648 }
649 EvmOutputSelection::LegacyAssembly => {
650 config.legacy_assembly = true;
651 }
652 EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources) => {
653 config.generated_sources = true;
654 }
655 EvmOutputSelection::ByteCode(BytecodeOutputSelection::Object) => {
656 config.bytecode = true;
657 }
658 EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap) => {
659 config.source_map = true;
660 }
661 EvmOutputSelection::DeployedByteCode(DeployedBytecodeOutputSelection::All)
662 | EvmOutputSelection::DeployedByteCode(
663 DeployedBytecodeOutputSelection::Object,
664 ) => {
665 config.deployed_bytecode = true;
666 }
667 _ => {}
668 },
669 ContractOutputSelection::Ewasm(_) => {
670 config.ewasm = true;
671 }
672 _ => {}
673 }
674 }
675 config
676 }
677
678 fn process_abi(&self, abi: Option<&JsonAbi>, file: &Path) -> Result<(), SolcError> {
679 if self.abi {
680 if let Some(abi) = abi {
681 let file = file.with_extension("abi.json");
682 fs::write(&file, serde_json::to_string_pretty(abi)?)
683 .map_err(|err| SolcError::io(err, file))?
684 }
685 }
686 Ok(())
687 }
688
689 fn process_metadata(&self, metadata: Option<&Metadata>, file: &Path) -> Result<(), SolcError> {
690 if self.metadata {
691 if let Some(metadata) = metadata {
692 let file = file.with_extension("metadata.json");
693 fs::write(&file, serde_json::to_string_pretty(metadata)?)
694 .map_err(|err| SolcError::io(err, file))?
695 }
696 }
697 Ok(())
698 }
699
700 fn process_ir(&self, ir: Option<&str>, file: &Path) -> Result<(), SolcError> {
701 if self.ir {
702 if let Some(ir) = ir {
703 let file = file.with_extension("ir");
704 fs::write(&file, ir).map_err(|err| SolcError::io(err, file))?
705 }
706 }
707 Ok(())
708 }
709
710 fn process_ir_optimized(
711 &self,
712 ir_optimized: Option<&str>,
713 file: &Path,
714 ) -> Result<(), SolcError> {
715 if self.ir_optimized {
716 if let Some(ir_optimized) = ir_optimized {
717 let file = file.with_extension("iropt");
718 fs::write(&file, ir_optimized).map_err(|err| SolcError::io(err, file))?
719 }
720 }
721 Ok(())
722 }
723
724 fn process_ewasm(&self, ewasm: Option<&Ewasm>, file: &Path) -> Result<(), SolcError> {
725 if self.ewasm {
726 if let Some(ewasm) = ewasm {
727 let file = file.with_extension("ewasm");
728 fs::write(&file, serde_json::to_vec_pretty(ewasm)?)
729 .map_err(|err| SolcError::io(err, file))?;
730 }
731 }
732 Ok(())
733 }
734
735 fn process_assembly(&self, asm: Option<&str>, file: &Path) -> Result<(), SolcError> {
736 if self.assembly {
737 if let Some(asm) = asm {
738 let file = file.with_extension("asm");
739 fs::write(&file, asm).map_err(|err| SolcError::io(err, file))?
740 }
741 }
742 Ok(())
743 }
744
745 fn process_legacy_assembly(
746 &self,
747 asm: Option<serde_json::Value>,
748 file: &Path,
749 ) -> Result<(), SolcError> {
750 if self.legacy_assembly {
751 if let Some(legacy_asm) = asm {
752 let file = file.with_extension("legacyAssembly.json");
753 fs::write(&file, format!("{legacy_asm}")).map_err(|err| SolcError::io(err, file))?
754 }
755 }
756 Ok(())
757 }
758
759 fn process_generated_sources(
760 &self,
761 generated_sources: Option<&Vec<GeneratedSource>>,
762 file: &Path,
763 ) -> Result<(), SolcError> {
764 if self.generated_sources {
765 if let Some(generated_sources) = generated_sources {
766 let file = file.with_extension("gensources");
767 fs::write(&file, serde_json::to_vec_pretty(generated_sources)?)
768 .map_err(|err| SolcError::io(err, file))?;
769 }
770 }
771 Ok(())
772 }
773
774 fn process_source_map(&self, source_map: Option<&str>, file: &Path) -> Result<(), SolcError> {
775 if self.source_map {
776 if let Some(source_map) = source_map {
777 let file = file.with_extension("sourcemap");
778 fs::write(&file, source_map).map_err(|err| SolcError::io(err, file))?
779 }
780 }
781 Ok(())
782 }
783
784 fn process_bytecode(
785 &self,
786 bytecode: Option<&BytecodeObject>,
787 file: &Path,
788 ) -> Result<(), SolcError> {
789 if self.bytecode {
790 if let Some(bytecode) = bytecode {
791 let code = hex::encode(bytecode.as_ref());
792 let file = file.with_extension("bin");
793 fs::write(&file, code).map_err(|err| SolcError::io(err, file))?
794 }
795 }
796 Ok(())
797 }
798
799 fn process_deployed_bytecode(
800 &self,
801 deployed: Option<&BytecodeObject>,
802 file: &Path,
803 ) -> Result<(), SolcError> {
804 if self.deployed_bytecode {
805 if let Some(deployed) = deployed {
806 let code = hex::encode(deployed.as_ref());
807 let file = file.with_extension("deployed-bin");
808 fs::write(&file, code).map_err(|err| SolcError::io(err, file))?
809 }
810 }
811 Ok(())
812 }
813
814 pub fn write_extras(&self, contract: &Contract, file: &Path) -> Result<(), SolcError> {
816 self.process_abi(contract.abi.as_ref(), file)?;
817 self.process_metadata(contract.metadata.as_ref().map(|m| &m.metadata), file)?;
818 self.process_ir(contract.ir.as_deref(), file)?;
819 self.process_ir_optimized(contract.ir_optimized.as_deref(), file)?;
820 self.process_ewasm(contract.ewasm.as_ref(), file)?;
821
822 let evm = contract.evm.as_ref();
823 self.process_assembly(evm.and_then(|evm| evm.assembly.as_deref()), file)?;
824 self.process_legacy_assembly(evm.and_then(|evm| evm.legacy_assembly.clone()), file)?;
825
826 let bytecode = evm.and_then(|evm| evm.bytecode.as_ref());
827 self.process_generated_sources(bytecode.map(|b| &b.generated_sources), file)?;
828
829 let deployed_bytecode = evm.and_then(|evm| evm.deployed_bytecode.as_ref());
830 self.process_source_map(bytecode.and_then(|b| b.source_map.as_deref()), file)?;
831 self.process_bytecode(bytecode.map(|b| &b.object), file)?;
832 self.process_deployed_bytecode(
833 deployed_bytecode.and_then(|d| d.bytecode.as_ref()).map(|b| &b.object),
834 file,
835 )?;
836
837 Ok(())
838 }
839}