Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forge): add accessList and cold/warm cheatcodes #10112

Merged
merged 4 commits into from
Mar 20, 2025

Conversation

grandizzy
Copy link
Collaborator

@grandizzy grandizzy commented Mar 18, 2025

Motivation

/// An EIP-2930 access list item.
struct AccessListItem {
    /// The address to be added in access list.
    address target;
    /// The storage keys to be added in access list.
    bytes32[] storageKeys;
}

/// Utility cheatcode to set an EIP-2930 access list for all subsequent transactions.
function accessList(AccessListItem[] calldata accessList) external;

/// Utility cheatcode to remove any EIP-2930 access list set by `accessList` cheatcode.
function noAccessList() external;

/// Utility cheatcode to mark specific storage slot as warm, simulating a prior read.
function warm(address target, bytes32 slot) external;

/// Utility cheatcode to mark specific storage slot as cold, simulating no prior read.
function cold(address target, bytes32 slot) external;

Solution

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

@grandizzy grandizzy changed the title [WIP] feat(forge): add cold/warm cheatcodes feat(forge): add accessList and cold/warm cheatcodes Mar 19, 2025
@grandizzy grandizzy added T-feature Type: feature C-forge Command: forge labels Mar 19, 2025
@grandizzy grandizzy marked this pull request as ready for review March 19, 2025 08:54
mattsse
mattsse previously approved these changes Mar 19, 2025
Copy link
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.

lgtm,

one concern re the accesslist cheatcode but we can also patch this separately if this is indeed not working as expected.

FYI @tynes

impl Cheatcode for noAccessListCall {
fn apply(&self, state: &mut Cheatcodes) -> Result {
let Self {} = self;
state.access_list = Some(alloy_rpc_types::AccessList::default());
Copy link
Member

Choose a reason for hiding this comment

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

should this just set to None

can we add a note here that this should set Some(empty) to force override this when applied to the evm env

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yep, add comment and set to empty only if prev set in 78da249

Comment on lines +671 to +674
// Apply EIP-2930 access lists.
if let Some(access_list) = &self.access_list {
ecx.env.tx.access_list = access_list.to_vec();
}
Copy link
Member

Choose a reason for hiding this comment

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

I'm not exactly sure if this has the desired effect, because idk when the evm does respect the configured accesslist, which could be already be before execution starts?@rakita

so maybe in order to get the desired effect here we'd need to replicate how accesslists are actually handled in the evm

Copy link
Collaborator Author

@grandizzy grandizzy Mar 19, 2025

Choose a reason for hiding this comment

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

would be great to have some insights @rakita, I assumed they're applied because the test below (included in PR) shows different gas usage (access list consist of single address, no storage slot, so the difference of 2400 sums up. If adding another address there's another 2400 of gas, if adding also a storage slot, an additional 1900 is added)

        uint256 initial = gasleft();
        write.setNumber(1);
        assertEq(initial - gasleft(), 26762);

        vm.accessList(accessList);
        uint256 initial1 = gasleft();
        write.setNumber(2);
        assertEq(initial1 - gasleft(), 29162);

        // reset access list, should take same gas as before
        vm.noAccessList();
        uint256 initial4 = gasleft();
        write.setNumber(4);
        assertEq(initial4 - gasleft(), 26762);

Copy link
Member

Choose a reason for hiding this comment

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

looks like it, I think we can proceed with this as is and change in case this isn't actually the case

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, they are loaded in execution, this is okay.

@grandizzy grandizzy merged commit 0dd4d31 into foundry-rs:master Mar 20, 2025
22 checks passed
@grandizzy grandizzy deleted the issue-10101 branch March 20, 2025 03:18
@DaniPopes
Copy link
Member

what about vm.cool?

@grandizzy
Copy link
Collaborator Author

what about vm.cool?

vm.cool is for entire account while the new one takes the slot to be set, I don't think they're redundant, wdyt?

@DaniPopes
Copy link
Member

right, but i would like for the names to align or at least provide some more context like coolSlot

@grandizzy
Copy link
Collaborator Author

right, but i would like for the names to align or at least provide some more context like coolSlot

makes sense, will follow up with a PR to rename coolSlot/warmSlot

@grandizzy
Copy link
Collaborator Author

right, but i would like for the names to align or at least provide some more context like coolSlot

follow-up pr #10128 pls check

grandizzy added a commit to foundry-rs/forge-std that referenced this pull request Mar 20, 2025
- adds new cheatcodes introduced in 
foundry-rs/foundry#10112
foundry-rs/foundry#10128
- add `cool` by removing Experimental status
- include `expectCreate` / `expectCreate2` and
`foundryVersionAtLeast/foundryVersionCmp`
@grandizzy grandizzy self-assigned this Mar 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-forge Command: forge T-feature Type: feature
Projects
Status: Completed
Development

Successfully merging this pull request may close these issues.

feat(cheatcodes): support access lists and storage slot state manipulation
4 participants