Skip to content

Commit

Permalink
feat(cast): decode external lib sigs from cached selectors (foundry-r…
Browse files Browse the repository at this point in the history
  • Loading branch information
grandizzy authored and rplusq committed Nov 29, 2024
1 parent a51bbe4 commit 182a184
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
91 changes: 91 additions & 0 deletions crates/cast/tests/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1841,3 +1841,94 @@ Transaction successfully executed.
"#]]);
});

// tests cast can decode external libraries traces with project cached selectors
forgetest_async!(decode_external_libraries_with_cached_selectors, |prj, cmd| {
let (api, handle) = anvil::spawn(NodeConfig::test()).await;

foundry_test_utils::util::initialize(prj.root());
prj.add_source(
"ExternalLib",
r#"
import "./CounterInExternalLib.sol";
library ExternalLib {
function updateCounterInExternalLib(CounterInExternalLib.Info storage counterInfo, uint256 counter) public {
counterInfo.counter = counter + 1;
}
}
"#,
)
.unwrap();
prj.add_source(
"CounterInExternalLib",
r#"
import "./ExternalLib.sol";
contract CounterInExternalLib {
struct Info {
uint256 counter;
}
Info info;
constructor() {
ExternalLib.updateCounterInExternalLib(info, 100);
}
}
"#,
)
.unwrap();
prj.add_script(
"CounterInExternalLibScript",
r#"
import "forge-std/Script.sol";
import {CounterInExternalLib} from "../src/CounterInExternalLib.sol";
contract CounterInExternalLibScript is Script {
function run() public {
vm.startBroadcast();
new CounterInExternalLib();
vm.stopBroadcast();
}
}
"#,
)
.unwrap();

cmd.args([
"script",
"--private-key",
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
"--rpc-url",
&handle.http_endpoint(),
"--broadcast",
"CounterInExternalLibScript",
])
.assert_success();

let tx_hash = api
.transaction_by_block_number_and_index(BlockNumberOrTag::Latest, Index::from(0))
.await
.unwrap()
.unwrap()
.tx_hash();

// Cache project selectors.
cmd.forge_fuse().set_current_dir(prj.root());
cmd.forge_fuse().args(["selectors", "cache"]).assert_success();

// Assert cast with local artifacts can decode external lib signature.
cmd.cast_fuse().set_current_dir(prj.root());
cmd.cast_fuse()
.args(["run", format!("{tx_hash}").as_str(), "--rpc-url", &handle.http_endpoint()])
.assert_success()
.stdout_eq(str![[r#"
...
Traces:
[37739] → new <unknown>@0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
├─ [22411] 0xfAb06527117d29EA121998AC4fAB9Fc88bF5f979::updateCounterInExternalLib(0, 100) [delegatecall]
│ └─ ← [Stop]
└─ ← [Return] 62 bytes of code
Transaction successfully executed.
[GAS]
"#]]);
});
9 changes: 9 additions & 0 deletions crates/cli/src/utils/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,15 @@ pub fn cache_local_signatures(output: &ProjectCompileOutput, cache_path: PathBuf
.events
.insert(event.selector().to_string(), event.full_signature());
}
// External libraries doesn't have functions included in abi, but `methodIdentifiers`.
if let Some(method_identifiers) = &artifact.method_identifiers {
method_identifiers.iter().for_each(|(signature, selector)| {
cached_signatures
.functions
.entry(format!("0x{selector}"))
.or_insert(signature.to_string());
});
}
}
});

Expand Down
7 changes: 5 additions & 2 deletions crates/evm/traces/src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,10 +689,13 @@ fn reconstruct_params(event: &Event, decoded: &DecodedEvent) -> Vec<DynSolValue>
let mut unindexed = 0;
let mut inputs = vec![];
for input in event.inputs.iter() {
if input.indexed {
// Prevent panic of event `Transfer(from, to)` decoded with a signature
// `Transfer(address indexed from, address indexed to, uint256 indexed tokenId)` by making
// sure the event inputs is not higher than decoded indexed / un-indexed values.
if input.indexed && indexed < decoded.indexed.len() {
inputs.push(decoded.indexed[indexed].clone());
indexed += 1;
} else {
} else if unindexed < decoded.body.len() {
inputs.push(decoded.body[unindexed].clone());
unindexed += 1;
}
Expand Down

0 comments on commit 182a184

Please sign in to comment.