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: gas snapshots over arbitrary sections #8952

Merged
merged 56 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
4ef2ac6
update internal naming
zerosnacks Sep 24, 2024
d90a09e
further internals
zerosnacks Sep 24, 2024
3d326d2
deprecate cheats
zerosnacks Sep 24, 2024
72b4e15
update Solidity tests and add dedicated test for testing deprecated c…
zerosnacks Sep 24, 2024
7fed284
clarify gas snapshots
zerosnacks Sep 24, 2024
d544326
fix build
zerosnacks Sep 24, 2024
8492c71
final fixes
zerosnacks Sep 24, 2024
a8f2ec5
fix build
zerosnacks Sep 24, 2024
2cca2c7
fix repro 6355 rename
zerosnacks Sep 24, 2024
9602aec
add gas snapshot setup from #8755
zerosnacks Sep 24, 2024
1ced509
fix build + clippy warnings
zerosnacks Sep 24, 2024
9348062
fix cheatcodes
zerosnacks Sep 24, 2024
094a4bb
account for fixed CREATE / CALL gas cost
zerosnacks Sep 24, 2024
e9bd560
remove import
zerosnacks Sep 24, 2024
836a400
add stipend
zerosnacks Sep 24, 2024
45ae718
Merge branch 'master' into zerosnacks/add-gas-section-snapshot-cheatc…
zerosnacks Sep 25, 2024
1ebd5c3
recalculate after a - b setup
zerosnacks Sep 25, 2024
9f8ea19
clear call_stipend, update tests
zerosnacks Sep 25, 2024
fd97339
Merge branch 'master' into zerosnacks/rename-state-snapshot
zerosnacks Sep 25, 2024
4114b07
Merge branch 'zerosnacks/rename-state-snapshot' into zerosnacks/add-g…
zerosnacks Sep 25, 2024
55d43f4
avoid double counting external calls
zerosnacks Sep 25, 2024
eb3f0ae
Merge branch 'zerosnacks/add-gas-section-snapshot-cheatcodes' of gith…
zerosnacks Sep 25, 2024
fe9822f
update cheatcodes, remove debug prints
zerosnacks Sep 25, 2024
1b2439c
enable assertions
zerosnacks Sep 25, 2024
aaee5d4
clean up tests
zerosnacks Sep 25, 2024
1bb65a7
clean up test names
zerosnacks Sep 25, 2024
040a2bf
Merge branch 'master' into zerosnacks/add-gas-section-snapshot-cheatc…
zerosnacks Sep 25, 2024
162ab95
remove snapshot directory on `forge clean`
zerosnacks Sep 25, 2024
50b8e54
Merge branch 'master' into zerosnacks/rename-state-snapshot
zerosnacks Sep 25, 2024
b78bd56
do not remove all snapshots by default due to multiple test suites be…
zerosnacks Sep 25, 2024
dd7c457
Merge branch 'zerosnacks/rename-state-snapshot' into zerosnacks/add-g…
zerosnacks Sep 25, 2024
7ae5dee
handle edge case where we ask to compare but file does not exist, rem…
zerosnacks Sep 25, 2024
54ea324
Merge branch 'zerosnacks/add-gas-section-snapshot-cheatcodes' of gith…
zerosnacks Sep 25, 2024
41800da
fix path issue when attempting removal
zerosnacks Sep 25, 2024
6408bb1
Update crates/cheatcodes/src/evm.rs
zerosnacks Sep 26, 2024
6c05e09
Update crates/cheatcodes/src/inspector.rs
zerosnacks Sep 26, 2024
fcd43e4
refactor, apply recommended changes for last_snapshot_group, last_sna…
zerosnacks Sep 26, 2024
c6b19b3
remove gas snapshots from fuzz tests for now: this is largely due to …
zerosnacks Sep 26, 2024
bca712f
fix clippy
zerosnacks Sep 26, 2024
d040ea7
Merge branch 'master' into zerosnacks/rename-state-snapshot-bu
zerosnacks Sep 26, 2024
6e0d85f
Merge branch 'zerosnacks/rename-state-snapshot-bu' into zerosnacks/ad…
zerosnacks Sep 26, 2024
23fdf66
avoid setting to 0 unnecessarily
zerosnacks Sep 26, 2024
86060d3
use if let Some
zerosnacks Sep 26, 2024
92384b2
improve comments, clarify use of last_gas_used != 0
zerosnacks Sep 26, 2024
b1e2567
merge in master
zerosnacks Sep 27, 2024
23d4410
Merge branch 'master' into zerosnacks/add-gas-section-snapshot-cheatc…
zerosnacks Sep 30, 2024
f789e3d
fix merge conflict issue
zerosnacks Sep 30, 2024
8f62030
fix arg ordering to address group naming regression
zerosnacks Sep 30, 2024
731cbe3
fix merge conflicts
zerosnacks Sep 30, 2024
d3d1229
fix import
zerosnacks Sep 30, 2024
ab2cded
move snapshot name derivation to helper
zerosnacks Oct 1, 2024
d3310f2
only skip initial call w/ overhead, no special handling for call frames
zerosnacks Oct 1, 2024
73b4f81
add flare test
zerosnacks Oct 1, 2024
b74ae33
style nits + use helper method
zerosnacks Oct 2, 2024
0511d24
Merge branch 'master' into zerosnacks/add-gas-section-snapshot-cheatc…
zerosnacks Oct 2, 2024
e7c9bf9
Merge branch 'master' into zerosnacks/add-gas-section-snapshot-cheatc…
zerosnacks Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
clean up tests
  • Loading branch information
zerosnacks committed Sep 25, 2024
commit aaee5d4118721ebf0d8649801cd77d11aef7073e
4 changes: 2 additions & 2 deletions crates/cheatcodes/assets/cheatcodes.json

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

4 changes: 2 additions & 2 deletions crates/cheatcodes/spec/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,11 +523,11 @@ interface Vm {

/// Snapshot capture the gas usage of the last call by name from the callee perspective.
#[cheatcode(group = Evm, safety = Unsafe)]
function snapshotGasLastCall(string calldata name) external;
function snapshotGasLastCall(string calldata name) external returns (uint256 gasUsed);

/// Snapshot capture the gas usage of the last call by name in a group from the callee perspective.
#[cheatcode(group = Evm, safety = Unsafe)]
function snapshotGasLastCall(string calldata group, string calldata name) external;
function snapshotGasLastCall(string calldata group, string calldata name) external returns (uint256 gasUsed);

/// Start a snapshot capture of the current gas usage by name.
/// The group name is derived from the contract name.
Expand Down
35 changes: 24 additions & 11 deletions crates/cheatcodes/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,14 +522,14 @@ impl Cheatcode for readCallersCall {
impl Cheatcode for snapshotValue_0Call {
fn apply_stateful<DB: DatabaseExt>(&self, ccx: &mut CheatsCtxt<DB>) -> Result {
let Self { name, value } = self;
inner_create_value_snapshot(ccx, None, Some(name.clone()), value.to_string())
inner_value_snapshot(ccx, None, Some(name.clone()), value.to_string())
}
}

impl Cheatcode for snapshotValue_1Call {
fn apply_stateful<DB: DatabaseExt>(&self, ccx: &mut CheatsCtxt<DB>) -> Result {
let Self { group, name, value } = self;
inner_create_value_snapshot(ccx, Some(group.clone()), Some(name.clone()), value.to_string())
inner_value_snapshot(ccx, Some(group.clone()), Some(name.clone()), value.to_string())
}
}

Expand All @@ -539,12 +539,7 @@ impl Cheatcode for snapshotGasLastCall_0Call {
let Some(last_call_gas) = &ccx.state.gas_metering.last_call_gas else {
bail!("no external call was made yet");
};
inner_create_value_snapshot(
ccx,
None,
Some(name.clone()),
last_call_gas.gasTotalUsed.to_string(),
)
inner_last_gas_snapshot(ccx, None, Some(name.clone()), last_call_gas.gasTotalUsed)
}
}

Expand All @@ -554,11 +549,11 @@ impl Cheatcode for snapshotGasLastCall_1Call {
let Some(last_call_gas) = &ccx.state.gas_metering.last_call_gas else {
bail!("no external call was made yet");
};
inner_create_value_snapshot(
inner_last_gas_snapshot(
ccx,
Some(group.clone()),
Some(name.clone()),
last_call_gas.gasTotalUsed.to_string(),
last_call_gas.gasTotalUsed,
)
}
}
Expand Down Expand Up @@ -787,7 +782,7 @@ fn inner_delete_state_snapshots<DB: DatabaseExt>(ccx: &mut CheatsCtxt<DB>) -> Re
Ok(Default::default())
}

fn inner_create_value_snapshot<DB: DatabaseExt>(
fn inner_value_snapshot<DB: DatabaseExt>(
ccx: &mut CheatsCtxt<DB>,
group: Option<String>,
name: Option<String>,
Expand All @@ -805,6 +800,24 @@ fn inner_create_value_snapshot<DB: DatabaseExt>(
Ok(Default::default())
}

fn inner_last_gas_snapshot<DB: DatabaseExt>(
ccx: &mut CheatsCtxt<DB>,
group: Option<String>,
name: Option<String>,
value: u64,
) -> Result {
let cheatcodes = ccx.state.clone();
let group = group
.as_deref()
.unwrap_or(cheatcodes.config.running_contract.as_ref().expect("expected running contract"))
.to_string();
let name = name.as_deref().unwrap_or("default").to_string();

ccx.state.gas_snapshots.entry(group).or_default().insert(name, value.to_string());

Ok(value.abi_encode())
}

fn inner_start_gas_snapshot<DB: DatabaseExt>(
ccx: &mut CheatsCtxt<DB>,
group: Option<String>,
Expand Down
4 changes: 2 additions & 2 deletions testdata/cheats/Vm.sol

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

89 changes: 32 additions & 57 deletions testdata/default/cheats/GasSnapshots.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,40 @@ import "cheats/Vm.sol";
contract GasSnapshotTest is DSTest {
Vm constant vm = Vm(HEVM_ADDRESS);

uint256 public slot0;
Flare public flare;
uint256 public slot;

function setUp() public {
flare = new Flare();
}

function testGasExternal() public {
vm.startSnapshotGas("testAssertGasExternal");
flare.run(1);
uint256 gasUsed = vm.stopSnapshotGas();

flare.update(2);

vm.stopSnapshotGas();
assertGt(gasUsed, 0);
}

function testGasInternal() public {
vm.startSnapshotGas("testAssertGasInternalA");

slot = 1;

slot0 = 1;
vm.stopSnapshotGas();

vm.startSnapshotGas("testAssertGasInternalB");

slot = 2;

slot0 = 2;
vm.stopSnapshotGas();

vm.startSnapshotGas("testAssertGasInternalC");

slot = 0;

slot0 = 0;
vm.stopSnapshotGas();

vm.startSnapshotGas("testAssertGasInternalD");

slot = 1;

slot0 = 1;
vm.stopSnapshotGas();

vm.startSnapshotGas("testAssertGasInternalE");

slot = 2;

slot0 = 2;
vm.stopSnapshotGas();
}

Expand Down Expand Up @@ -146,22 +136,25 @@ contract GasSnapshotTest is DSTest {
function testSnapshotGasLastCallName() public {
flare.run(1);

vm.snapshotGasLastCall("testSnapshotGasName");
uint256 gasUsed = vm.snapshotGasLastCall("testSnapshotGasLastCallName");
assertGt(gasUsed, 0);
}

// Writes to `CustomGroup` group with `testSnapshotGas` name.
function testSnapshotGasLastCallGroupName() public {
flare.run(1);

vm.snapshotGasLastCall("CustomGroup", "testSnapshotGasGroupName");
uint256 gasUsed = vm.snapshotGasLastCall("CustomGroup", "testSnapshotGasLastCallGroupName");
assertGt(gasUsed, 0);
}
}

contract GasComparisonTest is DSTest {
Vm constant vm = Vm(HEVM_ADDRESS);

uint256 public slotA;
uint256 public slotB;
uint256 public slot0;
uint256 public slot1;

uint256 public cachedGas;

function testGasComparisonEmpty() public {
Expand All @@ -180,12 +173,12 @@ contract GasComparisonTest is DSTest {
function testGasComparisonInternalCold() public {
// Start a cheatcode snapshot.
vm.startSnapshotGas("ComparisonGroup", "testGasComparisonInternalColdA");
slotA = 1;
slot0 = 1;
uint256 a = vm.stopSnapshotGas();

// Start a comparitive Solidity snapshot.
_snapStart();
slotB = 1;
slot1 = 1;
uint256 b = _snapEnd();
vm.snapshotValue("ComparisonGroup", "testGasComparisonInternalColdB", b);

Expand All @@ -194,17 +187,16 @@ contract GasComparisonTest is DSTest {

function testGasComparisonInternalWarm() public {
// Warm up the cache.
slotA = 1;
slotB = 1;
slot0 = 1;

// Start a cheatcode snapshot.
vm.startSnapshotGas("ComparisonGroup", "testGasComparisonInternalWarmA");
slotA = 2;
slot0 = 2;
uint256 a = vm.stopSnapshotGas();

// Start a comparitive Solidity snapshot.
_snapStart();
slotB = 2;
slot0 = 3;
uint256 b = _snapEnd();
vm.snapshotValue("ComparisonGroup", "testGasComparisonInternalWarmB", b);

Expand All @@ -213,19 +205,17 @@ contract GasComparisonTest is DSTest {

function testGasComparisonExternal() public {
// Warm up the cache.
TargetB targetA = new TargetB();
targetA.update(1);
TargetB targetB = new TargetB();
targetB.update(1);
TargetB target = new TargetB();
target.update(1);

// Start a cheatcode snapshot.
vm.startSnapshotGas("ComparisonGroup", "testGasComparisonExternalA");
targetA.update(2);
target.update(2);
uint256 a = vm.stopSnapshotGas();

// Start a comparitive Solidity snapshot.
_snapStart();
targetB.update(2);
target.update(3);
uint256 b = _snapEnd();
vm.snapshotValue("ComparisonGroup", "testGasComparisonExternalB", b);

Expand All @@ -235,36 +225,32 @@ contract GasComparisonTest is DSTest {
function testGasComparisonCreate() public {
// Start a cheatcode snapshot.
vm.startSnapshotGas("ComparisonGroup", "testGasComparisonCreateA");
new TargetEmptyA();
new TargetC();
uint256 a = vm.stopSnapshotGas();

// Start a comparitive Solidity snapshot.
_snapStart();
new TargetEmptyB();
new TargetC();
uint256 b = _snapEnd();

vm.snapshotValue("ComparisonGroup", "testGasComparisonCreateB", b);

vm.assertApproxEqAbs(a, b, 3);
}

function testGasComparisonNestedCalls() public {
// Warm up the cache.
TargetA targetA = new TargetA();
targetA.update(1);
TargetA targetB = new TargetA();
targetB.update(1);
TargetA target = new TargetA();
target.update(1);

// Start a cheatcode snapshot.
vm.startSnapshotGas("ComparisonGroup", "testGasComparisonNestedCallsA");
targetA.update(2);
target.update(2);
uint256 a = vm.stopSnapshotGas();

// Start a comparitive Solidity snapshot.
_snapStart();
targetB.update(2);
target.update(3);
uint256 b = _snapEnd();

vm.snapshotValue("ComparisonGroup", "testGasComparisonNestedCallsB", b);

vm.assertApproxEqAbs(a, b, 2);
Expand All @@ -284,22 +270,13 @@ contract GasComparisonTest is DSTest {
}

contract Flare {
TargetA public target;
bytes32[] public data;

constructor() {
target = new TargetA();
}

function run(uint256 n_) public {
for (uint256 i = 0; i < n_; i++) {
data.push(keccak256(abi.encodePacked(i)));
}
}

function update(uint256 x_) public {
target.update(x_);
}
}

contract TargetA {
Expand All @@ -322,6 +299,4 @@ contract TargetB {
}
}

contract TargetEmptyA {}

contract TargetEmptyB {}
contract TargetC {}
2 changes: 1 addition & 1 deletion testdata/foundry.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[profile.default]
# solc = "0.8.18"
solc = "0.8.18"
block_base_fee_per_gas = 0
block_coinbase = "0x0000000000000000000000000000000000000000"
block_difficulty = 0
Expand Down
Loading