Skip to content

Commit

Permalink
expand record access cheatcode interface
Browse files Browse the repository at this point in the history
Adds a couple more fields to recorded account and storage accesses.
  • Loading branch information
Inphi committed Nov 14, 2023
1 parent 3dbfaeb commit c217748
Show file tree
Hide file tree
Showing 9 changed files with 829 additions and 960 deletions.
9 changes: 3 additions & 6 deletions crates/abi/abi/HEVM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ struct DirEntry { string errorMessage; string path; uint64 depth; bool isDir; bo
struct FsMetadata { bool isDir; bool isSymlink; uint256 length; bool readOnly; uint256 modified; uint256 accessed; uint256 created; }
struct Wallet { address addr; uint256 publicKeyX; uint256 publicKeyY; uint256 privateKey; }
struct FfiResult { int32 exitCode; bytes stdout; bytes stderr; }
struct AccountAccess { address account; uint8 kind; bool initialized; uint256 value; bytes data; bool reverted; }
struct AccountAccess { address accessor; address account; uint256 kind; bool initialized; uint256 oldBalance; uint256 newBalance; bytes deployedCode; uint256 value; bytes data; bool reverted; StorageAccess[] storageAccesses; }
struct StorageAccess { address account; bytes32 slot; bool isWrite; bytes32 previousValue; bytes32 newValue; bool reverted; }

allowCheatcodes(address)
Expand Down Expand Up @@ -86,11 +86,8 @@ record()
accesses(address)(bytes32[], bytes32[])
skip(bool)

recordAccountAccesses()
getRecordedAccountAccesses()(AccountAccess[])

recordStorageAccesses()
getRecordedStorageAccesses()(StorageAccess[])
recordStateDiff()
getStateDiff()(AccountAccess[])

recordLogs()
getRecordedLogs()(Log[])
Expand Down
313 changes: 106 additions & 207 deletions crates/abi/src/bindings/hevm.rs

Large diffs are not rendered by default.

107 changes: 46 additions & 61 deletions crates/cheatcodes/assets/cheatcodes.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 17 additions & 14 deletions crates/cheatcodes/defs/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,23 +144,34 @@ interface Vm {
bytes stderr;
}

/// The result of a `getRecordedAccountAccess` call.
/// The result of a `getStateDiff` call.
struct AccountAccess {
/// What accessed the account.
address accessor;
/// The account whose storage was accessed.
/// It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
address account;
/// The kind of account access.
AccountAccessKind kind;
/// If the account is initialized or empty
bool initialized;
/// The previous account balance of the accessed account.
uint256 oldBalance;
/// The new account balance of the accessed account. This represents the balance change ignoring any reverts that may have occurred.
uint256 newBalance;
/// Code of the account deployed by CREATE.
bytes deployedCode;
/// Value passed along with the account access
uint256 value;
/// Input data provided to the CREATE or CALL
bytes data;
/// If this access was in a reverted context
bool reverted;
/// An ordered list of storage accesses made during an account access operation.
StorageAccess[] storageAccesses;
}

/// The result of a `getRecordedStorageAccess` call.
/// The storage accessed during an `AccountAccess`.
struct StorageAccess {
/// The account whose storage was accessed.
address account;
Expand Down Expand Up @@ -208,22 +219,14 @@ interface Vm {
#[cheatcode(group = Evm, safety = Safe)]
function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);

/// Record all account accesses as part of CREATE or CALL opcodes in order,
/// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
/// along with the context of the calls
#[cheatcode(group = Evm, safety = Safe)]
function recordAccountAccesses() external;
function recordStateDiff() external;

/// Returns an ordered array of all account accesses from a `vm.recordAccountAccess` session.
/// Returns an ordered array of all account accesses from a `vm.recordStateDiff` session.
#[cheatcode(group = Evm, safety = Safe)]
function getRecordedAccountAccesses() external returns (AccountAccess[] memory accesses);

/// Record all storage accesses in order, along with the context of the accesses
#[cheatcode(group = Evm, safety = Safe)]
function recordStorageAccesses() external;

/// Returns an ordered array of all storage accesses from a `vm.recordStorageAccess` session.
#[cheatcode(group = Evm, safety = Safe)]
function getRecordedStorageAccesses() external returns (StorageAccess[] memory accesses);
function getStateDiff() external returns (AccountAccess[] memory accesses);

// -------- Recording Map Writes --------

Expand Down
50 changes: 10 additions & 40 deletions crates/cheatcodes/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,33 +341,18 @@ impl Cheatcode for revertToCall {
}
}

impl Cheatcode for recordAccountAccessesCall {
impl Cheatcode for recordStateDiffCall {
fn apply(&self, state: &mut Cheatcodes) -> Result {
let Self {} = self;
state.recorded_account_accesses = Some(Default::default());
state.recorded_account_diffs = Some(Default::default());
Ok(Default::default())
}
}

impl Cheatcode for getRecordedAccountAccessesCall {
impl Cheatcode for getStateDiffCall {
fn apply(&self, state: &mut Cheatcodes) -> Result {
let Self {} = self;
get_recorded_account_accesses(state)
}
}

impl Cheatcode for recordStorageAccessesCall {
fn apply(&self, state: &mut Cheatcodes) -> Result {
let Self {} = self;
state.recorded_storage_accesses = Some(Default::default());
Ok(Default::default())
}
}

impl Cheatcode for getRecordedStorageAccessesCall {
fn apply(&self, state: &mut Cheatcodes) -> Result {
let Self {} = self;
get_recorded_storage_accesses(state)
get_state_diff(state)
}
}

Expand Down Expand Up @@ -439,32 +424,17 @@ pub(super) fn journaled_account<'a, DB: DatabaseExt>(
/// array of [AccountAccess]. If there are no accounts were
/// recorded as accessed, an abi encoded empty array is returned.
///
/// In the case where `getRecordedAccountAccesses` is called at a lower
/// depth than `recordAccountAccesses`, multiple `Vec<RecordedAccountAccesses>`
/// In the case where `getStateDiff` is called at a lower
/// depth than `recordStateDiff`, multiple `Vec<RecordedAccountAccesses>`
/// will be flattened, preserving the order of the accesses.
fn get_recorded_account_accesses(state: &mut Cheatcodes) -> Result {
let res = state.recorded_account_accesses
fn get_state_diff(state: &mut Cheatcodes) -> Result {
let res = state
.recorded_account_diffs
.replace(Default::default())
.unwrap_or_default()
.into_iter()
.flatten()
.map(|record| record.access)
.collect::<Vec<_>>();
Ok(res.abi_encode())
}

/// Consumes recorded storage accesses and returns them as an abi encoded
/// array of [StorageAccess]. If there are no storage accesses recorded,
/// an abi encoded empty array is returned.
///
/// In the case where `getRecordedStorageAccesses` is called at a lower
/// depth than `recordStorageAccesses`, multiple `Vec<RecordedStorageAccesses>`
/// will be flattened, preserving the order of the accesses.
fn get_recorded_storage_accesses(state: &mut Cheatcodes) -> Result {
let res = state.recorded_storage_accesses
.replace(Default::default())
.unwrap_or_default()
.into_iter()
.flatten()
.collect::<Vec<_>>();
Ok(res.abi_encode())
}
Loading

0 comments on commit c217748

Please sign in to comment.