Skip to content
Open
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Once a DVF is published, any user can choose to trust the signer of that DVF and
- [Etherscan Verified Contracts](#etherscan-verified-contracts)
- [Initialization by event topics](#initialization-by-event-topics)
- [Public libraries](#public-libraries)
- [Transaction inspection](#transaction-inspection)

7. [Common Problems](#common-problems)
8. [Getting Help](#getting-help)
Expand Down Expand Up @@ -574,6 +575,20 @@ dv init --project <PROJECT_PATH> --address <ADDRESS> --contractname <NAME> --lib

`<PATH>` is the path to the library contract file, relative to your project root. `<NAME>` is the name of the library contract. `<ADDRESS>` is the public address of the already deployed library.

### Transaction inspection

For some use cases, it is not necessary to inspect all transactions of a single contract, but rather all contracts in a single transaction (e.g., execution of a government proposal). This can be achieved with the command `inspect-tx`:

```
dv inspect-tx --txhash <TX_HASH> --chainid <CHAIN_ID>
```

`<TX_HASH>` is the hash of the transaction that should be inspected, `<CHAIN_ID>` the ID of the chain the transaction has been executed on.

The command will fetch all contracts that are touched during the transaction. For each of the contracts, raw state changes and emitted events are then fetched and displayed.

To see the decoded state changes and events (and to generate a DVF file), each contract can be configured in your `.dv_config.json` prior to (re-)running the command. For details, please refer to the [configuration specification](docs/config.md).

## Common Problems

Sometimes, it is possible that the `init` command cannot find a deployment transaction. In this case, you have the following options:
Expand Down
25 changes: 20 additions & 5 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ When running the `dvf` command, the default configuration file is expected at `$
| --- | --- |
| `rpc_urls` | Mapping from chain ID to RPC URL |
| `dvf_storage` | Folder where DVFs are stored |
| `trusted_signers`: | List of addresses of trusted signers |
| `trusted_signers` | List of addresses of trusted signers |
| `etherscan_global` | Etherscan configuration for all chains, optional |
| - `api_url` | Etherscan API URL |
| - `api_key` | Etherscan API Key |
Expand All @@ -23,13 +23,28 @@ When running the `dvf` command, the default configuration file is expected at `$
| - - `api_url` | Chain-specific Blockscout API URL |
| - - `api_key` | Chain-specific Blockscout API Key |
| `max_blocks_per_event_query` | Number of blocks that can be queried at once in `getLogs`, optional, defaults to 9999 |
| `web3_timeout` | Timeout in seconds for web3 RPC queries, optional, defaults to 700 |
| `web3_timeout` | Timeout in seconds for web3 RPC queries, optional, defaults to 5000 |
| `signer` | Configuration on how to sign, optional |
| - `wallet_address` | Address which is used to sign |
| - `wallet_type` | Can have different structure |
| - - `secret_key` | If secret key is used, hex string |
| - - `ledger_type` | If ledger is used, "LedgerLive" or "Legacy" |
| - - `ledger_index` | If ledger is used, Ledger Index to use |



| `projects` | List of project configurations for the `inspect-tx` command, optional |
| - `project_path` | Path to the root folder of the source code project |
| - `output_path` | Path to the output DVF file |
| - `environment` | Project's development environment, defaults to "Foundry" |
| - `artifacts_path` | Folder containing the project artifacts, defaults to "artifacts" |
| - `build_cache_path` | Folder containing build-info files, optional |
| - `libraries` | Library specifiers in the form Path:Name:Address, optional |
| - `address` | Address of the contract |
| - `chain_id` | Chain ID where the contract is deployed, optional |
| - `contract_name` | Name of the contract |
| - `deployment_tx` | Deployment transaction hash, optional |
| - `factory` | Treat this contract as a factory, which changes bytecode verification, defaults to false |
| - `implementation_config` | Optional implementation project configuration for proxy contracts |
| - - `project_path` | Path to the root folder of the implementation project |
| - - `environment` | Implementation project's development environment, defaults to "Foundry" |
| - - `artifacts_path` | Folder containing the implementation project artifacts, defaults to "artifacts" |
| - - `build_cache_path` | Folder containing the implementation contract's build-info files, optional |
| - - `contract_name` | Name of the implementation contract |
59 changes: 43 additions & 16 deletions lib/bytecode_verification/parse_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use alloy::json_abi::Constructor;
use alloy::primitives::U256;
use clap::ValueEnum;
use semver::Version;
use serde::{Deserialize, Serialize};
use serde_json;
use serde_json::Value;
use std::path::Path;
Expand Down Expand Up @@ -322,21 +323,47 @@ impl ProjectInfo {
},
);
// add base type
types.insert(
base_identifier.clone(),
TypeDescription {
encoding: String::from("inplace"),
label: type_name["baseType"]["typeDescriptions"]["typeString"]
.as_str()
.unwrap()
.to_string(),
number_of_bytes: type_defs.get_number_of_bytes(&base_identifier),
base: None,
key: None,
value: None,
members: None,
},
);
if base_identifier.starts_with("t_struct") {
let struct_slots: Vec<(u64, U256, Option<String>)> = vec![(
type_name["baseType"]["referencedDeclaration"]
.as_u64()
.unwrap(),
U256::from(0),
None,
)];
// we only need the types, so we use a dummy storage vector
let mut storage: Vec<StateVariable> = vec![];
for source in sources.values() {
if let Some(ast) = source.ast.clone() {
for node in &ast.nodes {
Self::find_storage_struct_data(
sources,
node,
type_defs,
&struct_slots,
types,
&mut storage,
);
}
}
}
} else {
types.insert(
base_identifier.clone(),
TypeDescription {
encoding: String::from("inplace"),
label: type_name["baseType"]["typeDescriptions"]["typeString"]
.as_str()
.unwrap()
.to_string(),
number_of_bytes: type_defs.get_number_of_bytes(&base_identifier),
base: None,
key: None,
value: None,
members: None,
},
);
}
} else if type_name["nodeType"] == "UserDefinedTypeName" {
// go deeper to extract inner structs
let identifier = type_name["typeDescriptions"]["typeIdentifier"]
Expand Down Expand Up @@ -1713,7 +1740,7 @@ impl ProjectInfo {
}
}

#[derive(ValueEnum, Copy, Clone, Eq, PartialEq)]
#[derive(ValueEnum, Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
pub enum Environment {
Foundry,
Hardhat,
Expand Down
Loading
Loading