Skip to content

Commit f97aeae

Browse files
VolodymyrBgjenpaffDaniPopes
authored
fix(linking): deep-merge link_references from creation and deployed bytecode (#11759)
* fix(linking): deep-merge link_references from creation and deployed bytecode * add a test case * Update lib.rs * Create samefile_union * Delete testdata/default/linking/samefile_union * Create SameFileUnion.t.sol * Update SameFileUnion.t.sol * Create Libs.sol * Update lib.rs * fmt * fixes * fmt * fmt * clippy * add one more test * Update Libs.sol * Update SameFileUnion.t.sol * Update lib.rs * revert * refactor --------- Co-authored-by: Jennifer <[email protected]> Co-authored-by: DaniPopes <[email protected]>
1 parent 3f10e79 commit f97aeae

File tree

3 files changed

+71
-9
lines changed

3 files changed

+71
-9
lines changed

crates/linking/src/lib.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use alloy_primitives::{Address, B256, Bytes};
99
use foundry_compilers::{
1010
Artifact, ArtifactId,
11-
artifacts::{CompactContractBytecodeCow, Libraries},
11+
artifacts::{CompactBytecode, CompactContractBytecodeCow, Libraries},
1212
contracts::ArtifactContracts,
1313
};
1414
use rayon::prelude::*;
@@ -105,23 +105,28 @@ impl<'a> Linker<'a> {
105105
) -> Result<(), LinkerError> {
106106
let contract = self.contracts.get(target).ok_or(LinkerError::MissingTargetArtifact)?;
107107

108-
let mut references = BTreeMap::new();
108+
let mut references: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
109+
let mut extend = |bytecode: &CompactBytecode| {
110+
for (file, libs) in &bytecode.link_references {
111+
references.entry(file.clone()).or_default().extend(libs.keys().cloned());
112+
}
113+
};
109114
if let Some(bytecode) = &contract.bytecode {
110-
references.extend(bytecode.link_references.clone());
115+
extend(bytecode);
111116
}
112117
if let Some(deployed_bytecode) = &contract.deployed_bytecode
113118
&& let Some(bytecode) = &deployed_bytecode.bytecode
114119
{
115-
references.extend(bytecode.link_references.clone());
120+
extend(bytecode);
116121
}
117122

118-
for (file, libs) in &references {
119-
for contract in libs.keys() {
123+
for (file, libs) in references {
124+
for name in libs {
120125
let id = self
121-
.find_artifact_id_by_library_path(file, contract, Some(&target.version))
126+
.find_artifact_id_by_library_path(&file, &name, Some(&target.version))
122127
.ok_or_else(|| LinkerError::MissingLibraryArtifact {
123-
file: file.to_string(),
124-
name: contract.to_string(),
128+
file: file.clone(),
129+
name,
125130
})?;
126131
if deps.insert(id) {
127132
self.collect_dependencies(id, deps)?;
@@ -744,6 +749,31 @@ mod tests {
744749
});
745750
}
746751

752+
#[test]
753+
fn link_samefile_union() {
754+
link_test(testdata().join("default/linking/samefile_union"), |linker| {
755+
linker
756+
.assert_dependencies("default/linking/samefile_union/Libs.sol:LInit", &[])
757+
.assert_dependencies("default/linking/samefile_union/Libs.sol:LRun", &[])
758+
.assert_dependencies(
759+
"default/linking/samefile_union/SameFileUnion.t.sol:UsesBoth",
760+
&[
761+
(
762+
"default/linking/samefile_union/Libs.sol:LInit",
763+
Address::from_str("0x5a443704dd4b594b382c22a083e2bd3090a6fef3")
764+
.unwrap(),
765+
),
766+
(
767+
"default/linking/samefile_union/Libs.sol:LRun",
768+
Address::from_str("0x47e9fbef8c83a1714f1951f142132e6e90f5fa5d")
769+
.unwrap(),
770+
),
771+
],
772+
)
773+
.test_with_sender_and_nonce(Address::default(), 1);
774+
});
775+
}
776+
747777
#[test]
748778
fn linking_failure() {
749779
let linker = LinkerTest::new(&testdata().join("default/linking/simple"), true);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.18;
3+
4+
library LInit {
5+
function f() external view returns (uint256) {
6+
return block.number;
7+
}
8+
}
9+
10+
library LRun {
11+
function g() external view returns (uint256) {
12+
return block.timestamp;
13+
}
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.18;
3+
4+
import "./Libs.sol";
5+
6+
contract UsesBoth {
7+
uint256 public x;
8+
9+
constructor() {
10+
// used only in creation bytecode
11+
x = LInit.f();
12+
}
13+
14+
function y() external view returns (uint256) {
15+
// used only in deployed bytecode
16+
return LRun.g();
17+
}
18+
}

0 commit comments

Comments
 (0)