Skip to content

Commit

Permalink
Record storage and account access cheatcodes
Browse files Browse the repository at this point in the history
Co-authored-by: James Wenzel <wenzel.james.r@gmail.com>
  • Loading branch information
2 people authored and Inphi committed Nov 9, 2023
1 parent 855d005 commit 3dbfaeb
Show file tree
Hide file tree
Showing 10 changed files with 1,866 additions and 10 deletions.
8 changes: 8 additions & 0 deletions crates/abi/abi/HEVM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ 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 StorageAccess { address account; bytes32 slot; bool isWrite; bytes32 previousValue; bytes32 newValue; bool reverted; }

allowCheatcodes(address)

Expand Down Expand Up @@ -84,6 +86,12 @@ record()
accesses(address)(bytes32[], bytes32[])
skip(bool)

recordAccountAccesses()
getRecordedAccountAccesses()(AccountAccess[])

recordStorageAccesses()
getRecordedStorageAccesses()(StorageAccess[])

recordLogs()
getRecordedLogs()(Log[])

Expand Down
340 changes: 340 additions & 0 deletions crates/abi/src/bindings/hevm.rs

Large diffs are not rendered by default.

170 changes: 170 additions & 0 deletions crates/cheatcodes/assets/cheatcodes.json

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

7 changes: 6 additions & 1 deletion crates/cheatcodes/defs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,13 @@ impl Cheatcodes<'static> {
Vm::FsMetadata::STRUCT.clone(),
Vm::Wallet::STRUCT.clone(),
Vm::FfiResult::STRUCT.clone(),
Vm::AccountAccess::STRUCT.clone(),
Vm::StorageAccess::STRUCT.clone(),
]),
enums: Cow::Owned(vec![
Vm::CallerMode::ENUM.clone(),
Vm::AccountAccessKind::ENUM.clone(),
]),
enums: Cow::Owned(vec![Vm::CallerMode::ENUM.clone()]),
errors: Vm::VM_ERRORS.iter().map(|&x| x.clone()).collect(),
events: Cow::Borrowed(&[]),
// events: Vm::VM_EVENTS.iter().map(|&x| x.clone()).collect(),
Expand Down
59 changes: 59 additions & 0 deletions crates/cheatcodes/defs/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ interface Vm {
RecurrentPrank,
}

/// The kind of account access that occurred.
enum AccountAccessKind {
/// The account was called.
Call,
/// THe account was created.
Create,
/// The account was selfdestruct.
SelfDestruct,
}

/// An Ethereum log. Returned by `getRecordedLogs`.
struct Log {
/// The topics of the log, including the signature, if any.
Expand Down Expand Up @@ -134,6 +144,38 @@ interface Vm {
bytes stderr;
}

/// The result of a `getRecordedAccountAccess` call.
struct AccountAccess {
/// The account whose storage was accessed.
address account;
/// The kind of account access.
AccountAccessKind kind;
/// If the account is initialized or empty
bool initialized;
/// 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;
}

/// The result of a `getRecordedStorageAccess` call.
struct StorageAccess {
/// The account whose storage was accessed.
address account;
/// The slot that was accessed.
bytes32 slot;
/// If the access was a write.
bool isWrite;
/// The previous value of the slot.
bytes32 previousValue;
/// The new value of the slot.
bytes32 newValue;
/// If the access was reverted.
bool reverted;
}

// ======== EVM ========

/// Gets the address for a given private key.
Expand Down Expand Up @@ -166,6 +208,23 @@ 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,
/// along with the context of the calls
#[cheatcode(group = Evm, safety = Safe)]
function recordAccountAccesses() external;

/// Returns an ordered array of all account accesses from a `vm.recordAccountAccess` 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);

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

/// Starts recording all map SSTOREs for later retrieval.
Expand Down
Loading

0 comments on commit 3dbfaeb

Please sign in to comment.