Skip to content

Commit d0e1f4f

Browse files
FEAT: Add new known addresses file argument to init (#93)
* feat init * Expand test * Fix formatting --------- Co-authored-by: Lothaire Aubergeon <lothaire.aubergeon@chainsecurity.com>
1 parent abeefa3 commit d0e1f4f

5 files changed

Lines changed: 107 additions & 6 deletions

File tree

lib/dvf/registry.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::path::Path;
55
use std::path::PathBuf;
66

77
use alloy::primitives::Address;
8+
use serde_json;
89
use tracing::debug;
910

1011
use crate::dvf::config::DVFConfig;
@@ -15,24 +16,51 @@ use crate::utils::pretty::{AddressType, ResolvedAddress};
1516
pub struct Registry {
1617
dvf_storage: PathBuf,
1718
trusted_signers: Vec<Address>,
19+
known_addresses: HashMap<u64, HashMap<Address, ResolvedAddress>>,
1820
}
1921

2022
impl Registry {
2123
pub fn from_config(config: &DVFConfig) -> Result<Self, ValidationError> {
24+
Self::from_config_with_known(config, None)
25+
}
26+
27+
pub fn from_config_with_known(
28+
config: &DVFConfig,
29+
known_addresses: Option<HashMap<u64, HashMap<Address, ResolvedAddress>>>,
30+
) -> Result<Self, ValidationError> {
2231
let dvf_storage = config.dvf_storage.clone();
2332

2433
Ok(Registry {
2534
dvf_storage,
2635
trusted_signers: config.trusted_signers.clone(),
36+
known_addresses: known_addresses.unwrap_or_default(),
2737
})
2838
}
2939

3040
pub fn is_trusted_signer(&self, address: &Address) -> bool {
3141
self.trusted_signers.contains(address)
3242
}
3343

44+
pub fn load_known_addresses_from_file(
45+
path: &Path,
46+
) -> Result<HashMap<u64, HashMap<Address, ResolvedAddress>>, ValidationError> {
47+
let f = fs::File::open(path)?;
48+
serde_json::from_reader::<_, HashMap<u64, HashMap<Address, ResolvedAddress>>>(f).map_err(
49+
|e| {
50+
ValidationError::Error(format!(
51+
"Could not parse known addresses file {}: {}",
52+
path.display(),
53+
e
54+
))
55+
},
56+
)
57+
}
58+
3459
pub fn collect_name_resolution(&self, chain_id: u64) -> HashMap<Address, ResolvedAddress> {
3560
let mut res: HashMap<Address, ResolvedAddress> = HashMap::new();
61+
if let Some(extra) = self.known_addresses.get(&chain_id) {
62+
res.extend(extra.clone());
63+
}
3664
self.collect_names_inner(&self.dvf_storage, &mut res, chain_id);
3765
res
3866
}
@@ -175,3 +203,61 @@ fn search_for_id(dir: &Path, id: &String) -> Result<Vec<PathBuf>, ValidationErro
175203
}
176204
Ok(results)
177205
}
206+
207+
#[cfg(test)]
208+
mod tests {
209+
use super::Registry;
210+
use crate::dvf::config::DVFConfig;
211+
use alloy::primitives::Address;
212+
use std::fs;
213+
use std::str::FromStr;
214+
use tempfile::tempdir;
215+
216+
#[test]
217+
fn load_known_addresses_and_collect() {
218+
let dir = tempdir().unwrap();
219+
let known_path = dir.path().join("known.json");
220+
221+
let address = "0x1111111111111111111111111111111111111111";
222+
let address2 = "0x1111111111111111111111111111111111111110";
223+
let name = "TestContract";
224+
let name2 = "TestContract2";
225+
226+
let json = format!(
227+
r#"
228+
{{
229+
"1": {{
230+
"{address}": {{
231+
"name": "{name}",
232+
"address_type": "Contract"
233+
}}
234+
}},
235+
"2": {{
236+
"{address2}": {{
237+
"name": "{name2}",
238+
"address_type": "Contract"
239+
}}
240+
}}
241+
}}
242+
"#
243+
);
244+
fs::write(&known_path, json).unwrap();
245+
246+
let known = Registry::load_known_addresses_from_file(&known_path).unwrap();
247+
248+
let mut config = DVFConfig::default();
249+
config.dvf_storage = dir.path().to_path_buf();
250+
251+
let registry = Registry::from_config_with_known(&config, Some(known)).unwrap();
252+
253+
let resolved = registry.collect_name_resolution(1);
254+
let addr = Address::from_str(address).unwrap();
255+
assert_eq!(resolved.get(&addr).unwrap().name, name);
256+
257+
let resolved2 = registry.collect_name_resolution(2);
258+
let addr2 = Address::from_str(address2).unwrap();
259+
assert_eq!(resolved2.get(&addr2).unwrap().name, name2);
260+
261+
assert!(registry.collect_name_resolution(137).is_empty());
262+
}
263+
}

lib/utils/pretty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::dvf::config::DVFConfig;
1717
use crate::dvf::registry::Registry;
1818
use crate::state::contract_state::ContractState;
1919

20-
#[derive(Deserialize, Debug)]
20+
#[derive(Deserialize, Debug, Clone)]
2121
pub enum AddressType {
2222
Token,
2323
Contract,
@@ -26,7 +26,7 @@ pub enum AddressType {
2626
Eoa,
2727
}
2828

29-
#[derive(Debug, Deserialize)]
29+
#[derive(Debug, Deserialize, Clone)]
3030
pub struct ResolvedAddress {
3131
pub address_type: AddressType,
3232
pub name: String,

src/dvf.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,11 @@ fn main() {
485485
arg!(<OUTPUT>)
486486
.help("Path of the generated DVF file")
487487
.required(true),
488+
)
489+
.arg(
490+
arg!(--knownaddressesfile <PATH>)
491+
.help("Optional JSON file with known addresses to include in name resolution")
492+
.value_parser(is_valid_path),
488493
),
489494
)
490495
.subcommand(
@@ -865,7 +870,12 @@ fn process(matches: ArgMatches) -> Result<(), ValidationError> {
865870
let mut dumped = parse::CompleteDVF::from_cli(sub_m)?;
866871
config.set_chain_id(dumped.chain_id)?;
867872

868-
let registry = registry::Registry::from_config(&config)?;
873+
let known_addresses = sub_m
874+
.get_one::<PathBuf>("knownaddressesfile")
875+
.map(|path| registry::Registry::load_known_addresses_from_file(path))
876+
.transpose()?;
877+
878+
let registry = registry::Registry::from_config_with_known(&config, known_addresses)?;
869879
let pretty_printer = PrettyPrinter::new(&config, Some(&registry));
870880

871881
// Parse optional initblock or take deployment_block_num + 1

tests/Contracts/src/CrazyHiddenStruct.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ contract CrazyHiddenStruct {
3939
bytes32 private constant StorageLocation2 = 0x852cbd6b186221cbf354c68826ab57cef1512cf2f5d959ca4501e155cbea7ae8;
4040
bytes32 private constant StorageLocation3 = 0x9482765040f1c978ae595e69b3ad0e4697ca0d1e0581a09be85cfb4a8462e752;
4141
bytes32 private constant StorageLocation4 = 0xe82aa111a62567be9a414850f7168d2e6c9f9d61a82b90598df0a59035cd53a6;
42-
bytes32 private constant DirectStorageLocation1 = 0xbfbceebbfa6e5996c6a04ac6db0e347528756a4f073935304cc6139dcc2fb653;
43-
bytes32 private constant DirectStorageLocation2 = 0x42d0407cb447148fd182bf527909ab1ba2fbaefe3f25cbe9851153586910b294;
42+
bytes32 private constant DirectStorageLocation1 =
43+
0xbfbceebbfa6e5996c6a04ac6db0e347528756a4f073935304cc6139dcc2fb653;
44+
bytes32 private constant DirectStorageLocation2 =
45+
0x42d0407cb447148fd182bf527909ab1ba2fbaefe3f25cbe9851153586910b294;
4446
bytes32 private constant KeccakStorageLocation1 = keccak256("keccak1");
4547
bytes32 private constant KeccakStorageLocation2 = bytes32(uint256(keccak256("keccak2")) - 1);
4648

tests/Contracts/src/MyToken.sol

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ interface IERC20Upgradeable {
7878
*/
7979
function transferFrom(address from, address to, uint256 amount) external returns (bool);
8080
}
81+
8182
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
8283

8384
/**
@@ -101,6 +102,7 @@ interface IERC20MetadataUpgradeable is IERC20Upgradeable {
101102
*/
102103
function decimals() external view returns (uint8);
103104
}
105+
104106
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
105107

106108
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
@@ -422,7 +424,8 @@ abstract contract Initializable {
422424
modifier initializer() {
423425
bool isTopLevelCall = !_initializing;
424426
require(
425-
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
427+
(isTopLevelCall && _initialized < 1)
428+
|| (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
426429
"Initializable: contract is already initialized"
427430
);
428431
_initialized = 1;

0 commit comments

Comments
 (0)