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(script): add warning for address(this) usage #10295

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

gap-editor
Copy link

Motivation

Closes #10289

Users can accidentally use address(this) within forge script contracts, often intending to refer to the script contract itself for operations like transferring ownership or sending tokens during deployment. However, the address(this) in a script context refers to a temporary, locally deployed contract instance used for the simulation. This address does not exist on the target network and relying on it leads to deployment errors or incorrect state on-chain.

This PR introduces a warning mechanism to alert users when address(this) is used during a forge script execution, helping prevent these common mistakes.

Solution

  1. Introduced ScriptAddressWarnInspector:

    • Defined a new revm::Inspector implementation named ScriptAddressWarnInspector within crates/evm/evm/src/inspectors/stack.rs.
    • This inspector implements the step method, which checks if the currently executing EVM opcode is ADDRESS (0x30).
    • If the ADDRESS opcode is detected, it prints a warning message to stderr: "forge script warning: Usage of \address(this)` detected. Script contracts are ephemeral and their addresses should not be relied upon."`
  2. Integrated into InspectorStack:

    • Added an optional address_warn_inspector field to the InspectorStackInner struct.
    • Added a corresponding address_warn boolean flag and a builder method .address_warn_inspector(bool) to InspectorStackBuilder.
    • Updated the InspectorStackBuilder::build method to instantiate ScriptAddressWarnInspector if the address_warn flag is true.
    • Modified the Inspector implementation for InspectorStackRefMut to invoke the step method of the address_warn_inspector if it's present.
  3. Enabled for forge script:

    • In crates/script/src/lib.rs, within the _get_runner function (which configures the Executor for scripts), modified the ExecutorBuilder chain to call .address_warn_inspector(true). This ensures the warning inspector is always active during forge script runs.

This approach leverages the existing revm inspector system to passively detect the opcode usage without significantly impacting performance and provides a clear warning directly to the user during script execution.

PR Checklist

  • Added Tests
  • Added Documentation
  • No Breaking changes

Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very supportive, some questions.

wdyt @klkvr @grandizzy

Comment on lines 658 to 660
/// An inspector that warns if the `ADDRESS` (0x30) opcode is used during script execution.
#[derive(Debug, Clone, Default)]
pub struct ScriptAddressWarnInspector;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have this twice now

Comment on lines 669 to 670
eprintln!("forge script warning: Usage of `address(this)` detected. Script contracts are ephemeral and their addresses should not be relied upon.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we also want a level style setting like "warn", "disallow" which could result in a revert?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah imo this should revert by default

Comment on lines +835 to +837
if self.in_inner_context {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not obvious why we need this now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this seems wrong

Comment on lines 768 to 770
&mut self.fuzzer,
&mut self.tracer,
&mut self.coverage,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to change this? I would prefer to not change order here without a strong reason

Comment on lines +835 to +837
if self.in_inner_context {
return;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this seems wrong

@@ -629,6 +636,7 @@ impl ScriptConfig {
if let Some((known_contracts, script_wallets, target)) = cheats_data {
builder = builder.inspectors(|stack| {
stack
.address_warn_inspector(true)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't feel right to have this as a entire separate inspector in the stack given that it pretty much does one simple check

should we move it to Cheatcodes @grandizzy ?

Copy link
Collaborator

@grandizzy grandizzy Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that would make sense to be in a sepparate one but more generic ScriptExecutionInspector where we could add more (maybe customizable checks like whitelist/blacklist addresses to call?) if needed?

Comment on lines 663 to 670
fn step(&mut self, interp: &mut Interpreter, _data: &mut EvmState<'_>) -> InstructionResult {
let opcode = interp.current_opcode();
if opcode == opcode::ADDRESS {
// Using eprintln directly might be too noisy or not the standard way Foundry handles warnings.
// Consider integrating with a logger or a dedicated warning mechanism if available.
// For now, printing to stderr demonstrates the concept.
eprintln!("forge script warning: Usage of `address(this)` detected. Script contracts are ephemeral and their addresses should not be relied upon.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe right now this will emit warnings for any ADDRESS usage in both tests and scripts

We want to only emit the warning if it's called in the context of script contract

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guess an ScriptExecutionInspector attached to script execution would handle this?

Copy link
Collaborator

@grandizzy grandizzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you pls add a test too?

@gap-editor gap-editor marked this pull request as draft April 12, 2025 11:13
@gap-editor gap-editor requested review from klkvr and mattsse April 12, 2025 11:42
@gap-editor gap-editor marked this pull request as ready for review April 13, 2025 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

feat(forge script): add warning if address(this) is used
4 participants