Skip to content

Commit ae89c92

Browse files
authored
feat: cool cheatcode (foundry-rs#5830)
* feat: `cool` cheatcode * refactor: extract to a function, remove check
1 parent a804703 commit ae89c92

File tree

5 files changed

+130
-0
lines changed

5 files changed

+130
-0
lines changed

crates/abi/abi/HEVM.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ fee(uint256)
2222
coinbase(address)
2323
store(address,bytes32,bytes32)
2424
load(address,bytes32)(bytes32)
25+
cool(address)
2526

2627
setEnv(string,string)
2728
envBool(string)(bool)

crates/abi/src/bindings/hevm.rs

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/evm/src/executor/inspector/cheatcodes/env.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,18 @@ fn add_breakpoint(state: &mut Cheatcodes, caller: Address, inner: &str, add: boo
318318
Ok(Bytes::new())
319319
}
320320

321+
// mark the slots of an account and the account address as cold
322+
fn cool_account<DB: DatabaseExt>(data: &mut EVMData<'_, DB>, address: Address) -> Result {
323+
if let Some(account) = data.journaled_state.state.get_mut(&h160_to_b160(address)) {
324+
if account.is_touched() {
325+
account.unmark_touch();
326+
}
327+
account.storage.clear();
328+
}
329+
330+
Ok(Bytes::new())
331+
}
332+
321333
#[instrument(level = "error", name = "env", target = "evm::cheatcodes", skip_all)]
322334
pub fn apply<DB: DatabaseExt>(
323335
state: &mut Cheatcodes,
@@ -387,6 +399,7 @@ pub fn apply<DB: DatabaseExt>(
387399
)?;
388400
ru256_to_u256(val).encode().into()
389401
}
402+
HEVMCalls::Cool(inner) => cool_account(data, inner.0)?,
390403
HEVMCalls::Breakpoint0(inner) => add_breakpoint(state, caller, &inner.0, true)?,
391404
HEVMCalls::Breakpoint1(inner) => add_breakpoint(state, caller, &inner.0, inner.1)?,
392405
HEVMCalls::Etch(inner) => {

testdata/cheats/Cool.t.sol

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: Unlicense
2+
pragma solidity 0.8.18;
3+
4+
import "../lib/ds-test/src/test.sol";
5+
import "./Vm.sol";
6+
7+
contract CoolTest is DSTest {
8+
Vm constant vm = Vm(HEVM_ADDRESS);
9+
uint256 public slot0 = 1;
10+
11+
function testCool_SLOAD_normal() public {
12+
uint256 startGas;
13+
uint256 endGas;
14+
uint256 val;
15+
uint256 beforeCoolGas;
16+
uint256 noCoolGas;
17+
18+
startGas = gasleft();
19+
val = slot0;
20+
endGas = gasleft();
21+
beforeCoolGas = startGas - endGas;
22+
23+
startGas = gasleft();
24+
val = slot0;
25+
endGas = gasleft();
26+
noCoolGas = startGas - endGas;
27+
28+
assertGt(beforeCoolGas, noCoolGas);
29+
}
30+
31+
function testCool_SLOAD() public {
32+
uint256 startGas;
33+
uint256 endGas;
34+
uint256 val;
35+
uint256 beforeCoolGas;
36+
uint256 afterCoolGas;
37+
uint256 noCoolGas;
38+
39+
startGas = gasleft();
40+
val = slot0;
41+
endGas = gasleft();
42+
beforeCoolGas = startGas - endGas;
43+
44+
vm.cool(address(this));
45+
46+
startGas = gasleft();
47+
val = slot0;
48+
endGas = gasleft();
49+
afterCoolGas = startGas - endGas;
50+
51+
assertEq(beforeCoolGas, afterCoolGas);
52+
53+
startGas = gasleft();
54+
val = slot0;
55+
endGas = gasleft();
56+
noCoolGas = startGas - endGas;
57+
58+
assertGt(beforeCoolGas, noCoolGas);
59+
}
60+
}

testdata/cheats/Vm.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ interface Vm {
9696
// Stores a value to an address' storage slot, (who, slot, value)
9797
function store(address, bytes32, bytes32) external;
9898

99+
// Cools off a warm address and its storage slots
100+
function cool(address) external;
101+
99102
// Signs data, (privateKey, digest) => (v, r, s)
100103
function sign(uint256, bytes32) external returns (uint8, bytes32, bytes32);
101104

0 commit comments

Comments
 (0)