Skip to content

Commit 5580f96

Browse files
authored
Merge branch 'master' into adding_support_etherscan_v2
2 parents 3d60de4 + 96c40b6 commit 5580f96

File tree

13 files changed

+125
-28
lines changed

13 files changed

+125
-28
lines changed

crates/cheatcodes/assets/cheatcodes.json

+21-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cheatcodes/spec/src/vm.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,15 @@ interface Vm {
399399

400400
// -------- Record Storage --------
401401

402-
/// Records all storage reads and writes.
402+
/// Records all storage reads and writes. Use `accesses` to get the recorded data.
403+
/// Subsequent calls to `record` will clear the previous data.
403404
#[cheatcode(group = Evm, safety = Safe)]
404405
function record() external;
405406

407+
/// Stops recording storage reads and writes.
408+
#[cheatcode(group = Evm, safety = Safe)]
409+
function stopRecord() external;
410+
406411
/// Gets all accessed reads and write slot from a `vm.record` session, for a given address.
407412
#[cheatcode(group = Evm, safety = Safe)]
408413
function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);

crates/cheatcodes/src/evm.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ impl RecordAccess {
5656
self.record_read(target, slot);
5757
self.writes.entry(target).or_default().push(slot);
5858
}
59+
60+
/// Clears the recorded reads and writes.
61+
pub fn clear(&mut self) {
62+
// Also frees memory.
63+
*self = Default::default();
64+
}
5965
}
6066

6167
/// Records the `snapshotGas*` cheatcodes.
@@ -280,24 +286,26 @@ impl Cheatcode for dumpStateCall {
280286
impl Cheatcode for recordCall {
281287
fn apply(&self, state: &mut Cheatcodes) -> Result {
282288
let Self {} = self;
283-
state.accesses = Some(Default::default());
289+
state.recording_accesses = true;
290+
state.accesses.clear();
291+
Ok(Default::default())
292+
}
293+
}
294+
295+
impl Cheatcode for stopRecordCall {
296+
fn apply(&self, state: &mut Cheatcodes) -> Result {
297+
state.recording_accesses = false;
284298
Ok(Default::default())
285299
}
286300
}
287301

288302
impl Cheatcode for accessesCall {
289303
fn apply(&self, state: &mut Cheatcodes) -> Result {
290304
let Self { target } = *self;
291-
let result = state
292-
.accesses
293-
.as_mut()
294-
.map(|accesses| {
295-
(
296-
&accesses.reads.entry(target).or_default()[..],
297-
&accesses.writes.entry(target).or_default()[..],
298-
)
299-
})
300-
.unwrap_or_default();
305+
let result = (
306+
state.accesses.reads.entry(target).or_default().as_slice(),
307+
state.accesses.writes.entry(target).or_default().as_slice(),
308+
);
301309
Ok(result.abi_encode_params())
302310
}
303311
}

crates/cheatcodes/src/inspector.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,10 @@ pub struct Cheatcodes {
420420
pub fork_revert_diagnostic: Option<RevertDiagnostic>,
421421

422422
/// Recorded storage reads and writes
423-
pub accesses: Option<RecordAccess>,
423+
pub accesses: RecordAccess,
424+
425+
/// Whether storage access recording is currently active
426+
pub recording_accesses: bool,
424427

425428
/// Recorded account accesses (calls, creates) organized by relative call depth, where the
426429
/// topmost vector corresponds to accesses at the depth at which account access recording
@@ -538,6 +541,7 @@ impl Cheatcodes {
538541
assume_no_revert: Default::default(),
539542
fork_revert_diagnostic: Default::default(),
540543
accesses: Default::default(),
544+
recording_accesses: Default::default(),
541545
recorded_account_diffs_stack: Default::default(),
542546
recorded_logs: Default::default(),
543547
record_debug_steps_info: Default::default(),
@@ -1332,7 +1336,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes {
13321336
}
13331337

13341338
// `record`: record storage reads and writes.
1335-
if self.accesses.is_some() {
1339+
if self.recording_accesses {
13361340
self.record_accesses(interpreter);
13371341
}
13381342

@@ -1945,7 +1949,7 @@ impl Cheatcodes {
19451949
/// Records storage slots reads and writes.
19461950
#[cold]
19471951
fn record_accesses(&mut self, interpreter: &mut Interpreter) {
1948-
let Some(access) = &mut self.accesses else { return };
1952+
let access = &mut self.accesses;
19491953
match interpreter.current_opcode() {
19501954
op::SLOAD => {
19511955
let key = try_or_return!(interpreter.stack().peek(0));

crates/config/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ pub struct Config {
523523
#[serde(default)]
524524
pub compilation_restrictions: Vec<CompilationRestrictions>,
525525

526+
/// Whether to enable script execution protection.
527+
pub script_execution_protection: bool,
528+
526529
/// PRIVATE: This structure may grow, As such, constructing this structure should
527530
/// _always_ be done using a public constructor or update syntax:
528531
///
@@ -2412,6 +2415,7 @@ impl Default for Config {
24122415
additional_compiler_profiles: Default::default(),
24132416
compilation_restrictions: Default::default(),
24142417
eof: false,
2418+
script_execution_protection: true,
24152419
_non_exhaustive: (),
24162420
}
24172421
}

crates/evm/evm/src/executors/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ impl Executor {
258258
}
259259

260260
#[inline]
261-
pub fn set_script(&mut self, script_address: Address) {
261+
pub fn set_script_execution(&mut self, script_address: Address) {
262262
self.inspector_mut().script(script_address);
263263
}
264264

crates/forge/tests/cli/config.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ forgetest!(can_extract_config_values, |prj, cmd| {
169169
additional_compiler_profiles: Default::default(),
170170
compilation_restrictions: Default::default(),
171171
eof: false,
172+
script_execution_protection: true,
172173
_non_exhaustive: (),
173174
};
174175
prj.write_config(input.clone());
@@ -1041,6 +1042,7 @@ transaction_timeout = 120
10411042
eof = false
10421043
additional_compiler_profiles = []
10431044
compilation_restrictions = []
1045+
script_execution_protection = true
10441046
10451047
[profile.default.rpc_storage_caching]
10461048
chains = "all"
@@ -1298,7 +1300,8 @@ exclude = []
12981300
"transaction_timeout": 120,
12991301
"eof": false,
13001302
"additional_compiler_profiles": [],
1301-
"compilation_restrictions": []
1303+
"compilation_restrictions": [],
1304+
"script_execution_protection": true
13021305
}
13031306
13041307
"#]]);

crates/forge/tests/cli/script.rs

+11
Original file line numberDiff line numberDiff line change
@@ -2668,6 +2668,17 @@ Error: Usage of `address(this)` detected in script contract. Script contracts ar
26682668
Error: script failed: <empty revert data>
26692669
...
26702670
2671+
"#]]);
2672+
2673+
// Disable script protection.
2674+
prj.update_config(|config| {
2675+
config.script_execution_protection = false;
2676+
});
2677+
cmd.assert_success().stdout_eq(str![[r#"
2678+
...
2679+
Script ran successfully.
2680+
...
2681+
26712682
"#]]);
26722683
});
26732684

crates/script/src/execute.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,8 @@ impl PreExecutionState {
144144
&self.build_data.predeploy_libraries,
145145
self.execution_data.bytecode.clone(),
146146
needs_setup(&self.execution_data.abi),
147-
self.script_config.sender_nonce,
147+
&self.script_config,
148148
self.args.broadcast,
149-
self.script_config.evm_opts.fork_url.is_none(),
150149
)?;
151150

152151
if setup_result.success {

crates/script/src/runner.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::ScriptResult;
1+
use super::{ScriptConfig, ScriptResult};
22
use crate::build::ScriptPredeployLibraries;
33
use alloy_eips::eip7702::SignedAuthorization;
44
use alloy_primitives::{Address, Bytes, TxKind, U256};
@@ -33,9 +33,8 @@ impl ScriptRunner {
3333
libraries: &ScriptPredeployLibraries,
3434
code: Bytes,
3535
setup: bool,
36-
sender_nonce: u64,
36+
script_config: &ScriptConfig,
3737
is_broadcast: bool,
38-
need_create2_deployer: bool,
3938
) -> Result<(Address, ScriptResult)> {
4039
trace!(target: "script", "executing setUP()");
4140

@@ -45,11 +44,12 @@ impl ScriptRunner {
4544
self.executor.set_balance(self.evm_opts.sender, U256::MAX)?;
4645
}
4746

48-
if need_create2_deployer {
47+
if script_config.evm_opts.fork_url.is_none() {
4948
self.executor.deploy_create2_deployer()?;
5049
}
5150
}
5251

52+
let sender_nonce = script_config.sender_nonce;
5353
self.executor.set_nonce(self.evm_opts.sender, sender_nonce)?;
5454

5555
// We max out their balance so that they can deploy and make calls.
@@ -158,7 +158,9 @@ impl ScriptRunner {
158158
}
159159

160160
// set script address to be used by execution inspector
161-
self.executor.set_script(address);
161+
if script_config.config.script_execution_protection {
162+
self.executor.set_script_execution(address);
163+
}
162164

163165
traces.extend(constructor_traces.map(|traces| (TraceKind::Deployment, traces)));
164166

foundryup/foundryup

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -eo pipefail
44
# NOTE: if you make modifications to this script, please increment the version number.
55
# Major / minor: incremented for each stable release of Foundry.
66
# Patch: incremented for each change between stable releases.
7-
FOUNDRYUP_INSTALLER_VERSION="1.0.1"
7+
FOUNDRYUP_INSTALLER_VERSION="1.1.0"
88

99
BASE_DIR=${XDG_CONFIG_HOME:-$HOME}
1010
FOUNDRY_DIR=${FOUNDRY_DIR:-"$BASE_DIR/.foundry"}
@@ -118,7 +118,7 @@ main() {
118118
PLATFORM=$(tolower "${FOUNDRYUP_PLATFORM:-$uname_s}")
119119
EXT="tar.gz"
120120
case $PLATFORM in
121-
linux) ;;
121+
linux|alpine) ;;
122122
darwin|mac*)
123123
PLATFORM="darwin"
124124
;;
@@ -272,7 +272,7 @@ OPTIONS:
272272
-p, --path Build and install a local repository
273273
-j, --jobs Number of CPUs to use for building Foundry (default: all CPUs)
274274
--arch Install a specific architecture (supports amd64 and arm64)
275-
--platform Install a specific platform (supports win32, linux, and darwin)
275+
--platform Install a specific platform (supports win32, linux, darwin and alpine)
276276
EOF
277277
}
278278

testdata/cheats/Vm.sol

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testdata/default/cheats/Record.t.sol

+40
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,44 @@ contract RecordTest is DSTest {
5353
assertEq(innerWrites.length, 1, "number of nested writes is incorrect");
5454
assertEq(innerWrites[0], bytes32(uint256(2)), "key for nested write is incorrect");
5555
}
56+
57+
function testStopRecordAccess() public {
58+
RecordAccess target = new RecordAccess();
59+
60+
// Start recording
61+
vm.record();
62+
NestedRecordAccess inner = target.record();
63+
64+
// Verify Records
65+
(bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(target));
66+
67+
assertEq(reads.length, 2, "number of reads is incorrect");
68+
assertEq(reads[0], bytes32(uint256(1)), "key for read 0 is incorrect");
69+
assertEq(reads[1], bytes32(uint256(1)), "key for read 1 is incorrect");
70+
71+
assertEq(writes.length, 1, "number of writes is incorrect");
72+
assertEq(writes[0], bytes32(uint256(1)), "key for write is incorrect");
73+
74+
vm.stopRecord();
75+
inner = target.record();
76+
77+
// Verify that there are no new Records
78+
(reads, writes) = vm.accesses(address(target));
79+
80+
assertEq(reads.length, 2, "number of reads is incorrect");
81+
assertEq(reads[0], bytes32(uint256(1)), "key for read 0 is incorrect");
82+
assertEq(reads[1], bytes32(uint256(1)), "key for read 1 is incorrect");
83+
84+
assertEq(writes.length, 1, "number of writes is incorrect");
85+
assertEq(writes[0], bytes32(uint256(1)), "key for write is incorrect");
86+
87+
vm.record();
88+
vm.stopRecord();
89+
90+
// verify reset all records
91+
(reads, writes) = vm.accesses(address(target));
92+
93+
assertEq(reads.length, 0, "number of reads is incorrect");
94+
assertEq(writes.length, 0, "number of writes is incorrect");
95+
}
5696
}

0 commit comments

Comments
 (0)