Skip to content

feat(cheatcodes): add vm.getSelectors cheatcode#14372

Open
zacharyftw wants to merge 2 commits intofoundry-rs:masterfrom
zacharyftw:feat/get-selectors
Open

feat(cheatcodes): add vm.getSelectors cheatcode#14372
zacharyftw wants to merge 2 commits intofoundry-rs:masterfrom
zacharyftw:feat/get-selectors

Conversation

@zacharyftw
Copy link
Copy Markdown

Motivation

Retrieving function selectors currently requires ffi + forge inspect or manually parsing artifact JSON with vm.readFile. Both are clunky and clutter test traces. Closes #11484

Solution

Add vm.getSelectors(string calldata artifactPath) cheatcode that returns bytes4[] of all function selectors from a contract's ABI. Supports the same artifact path formats as vm.getCode.

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new filesystem cheatcode to extract function selectors directly from compiled contract artifacts, reducing the need for ffi/forge inspect workflows in Solidity tests.

Changes:

  • Introduces vm.getSelectors(string artifactPath) returning bytes4[] from an artifact ABI.
  • Implements artifact ABI resolution in Rust cheatcodes execution and wires the new cheatcode into the spec/assets.
  • Adds Solidity tests covering several artifact path formats.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
testdata/utils/Vm.sol Exposes the new getSelectors function on the Vm interface used by tests.
testdata/default/cheats/GetSelectors.t.sol Adds a new cheatcode test suite for selector retrieval via different path forms.
crates/cheatcodes/src/fs.rs Implements the getSelectors cheatcode and artifact-ABI lookup helper.
crates/cheatcodes/spec/src/vm.rs Updates the cheatcode spec interface/docs for getSelectors.
crates/cheatcodes/assets/cheatcodes.json Registers getSelectors in the generated cheatcodes metadata (signature/selector/docs).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/cheatcodes/src/fs.rs Outdated
Comment on lines +615 to +621
/// Returns the ABI of a matching artifact from the given path.
///
/// See [`get_artifact_code`] for the supported path formats.
fn get_artifact_abi<FEN: FoundryEvmNetwork>(
state: &Cheatcodes<FEN>,
path: &str,
) -> Result<JsonAbi> {
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_artifact_abi largely duplicates the path parsing + artifact selection logic from get_artifact_code. This makes it easy for the two to drift (e.g., if a new path format is added to one but not the other). Consider extracting the shared parsing/matching into a helper that returns the resolved artifact (or resolved artifact path), then have get_artifact_code and get_artifact_abi build on that.

Copilot uses AI. Check for mistakes.
bytes4[] memory selectors = vm.getSelectors("cheats/GetSelectors.t.sol:TargetContract");
assertEq(selectors.length, 3, "should return 3 selectors");
}

Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite covers name, name+version, and full-path inputs, but it doesn’t exercise the .json artifact-path variant mentioned in the docs, nor any failure modes (e.g., unknown contract name / wrong version) to assert the revert message. Adding at least one .json-path test and one negative test would help ensure the path resolution and error behavior stay stable.

Suggested change
function testGetSelectorsByJsonArtifactPath() public {
bytes4[] memory selectors = vm.getSelectors("cheats/GetSelectors.t.sol/TargetContract.json");
assertEq(selectors.length, 3, "should return 3 selectors");
assertTrue(_contains(selectors, TargetContract.foo.selector), "should contain foo selector");
assertTrue(_contains(selectors, TargetContract.bar.selector), "should contain bar selector");
assertTrue(_contains(selectors, TargetContract.baz.selector), "should contain baz selector");
}
function testGetSelectorsUnknownContractReverts() public {
vm.expectRevert();
vm.getSelectors("UnknownTargetContract");
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not opposed to this but I think we should avoid adding another standalone artifact parsing fn

Comment thread crates/cheatcodes/src/fs.rs Outdated
/// Returns the ABI of a matching artifact from the given path.
///
/// See [`get_artifact_code`] for the supported path formats.
fn get_artifact_abi<FEN: FoundryEvmNetwork>(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can unify this with existing function with get_artifact_code

@zacharyftw
Copy link
Copy Markdown
Author

@mattsse i have dropped the dup fn 👍🏽

Copy link
Copy Markdown
Collaborator

@mablr mablr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sgtm, pending @mattsse's approval.

@mablr mablr requested a review from mattsse April 23, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

feat(cheatcodes): add vm.getSelectors(name) cheatcode to get a list of all selectors

5 participants