foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.12k stars 1.68k forks source link

bug(`forge script`): duplicate `vm.prompt` display in script with external libs #8658

Open beeb opened 1 month ago

beeb commented 1 month ago

Component

Forge

Have you ensured that all of these are up to date?

What version of Foundry are you on?

forge 0.2.0 (a0a0020 2024-08-12T00:21:34.427762642Z)

What command(s) is the bug in?

forge script

Operating System

Linux

Describe the bug

Repro code: https://github.com/beeb/foundry-repro-prompt-lib

When a contract must be linked against external libraries, and a Foundry script deploys such contract, prompts are shown twice.

Reproduction steps:

  1. Launch an anvil instance: anvil -a 1
  2. Launch script: forge script -f http://localhost:8545 --broadcast script/Counter.s.sol:CounterScript
  3. Observe that a prompt shows up and paste the first anvil private key: 0xac0974bec3...
  4. Observe that a second identical prompt is displayed

If the deployed contract does not have external libraries that must be linked, the problem does not happen.

samooyo commented 1 month ago

I encountered the same issue. I believe there's a problem with the deployment of external libraries and the prompt sequence. When using a script where external libraries need to be deployed, this task is performed first, even before the run function starts executing. However when a prompt is included in the script, the deployment of these libraries is delayed, awaiting user input, which maybe conflicts with the deployment process.

The inputs from the second prompt overwrite those from the first.

Initially, I thought the duplicated prompt was related to the simulation of the script, but using the --skip-simulation option didn't change anything.

mds1 commented 1 month ago

@klkvr Potentially related to https://github.com/foundry-rs/foundry/issues/8639?

klkvr commented 1 month ago

This is happening because of the way scripts handle external libraries deployment when private key is not known before running the script. Forge needs to know which address to use to deploy external libraries, and if the only signer is being resolved dynamically in script (in this case, by prompting private key), then we need to run script second time with correctly calculated library addresses, deployed by the prompted private key

This is is not specific to vm.prompt, scripts would be executed twice also in cases when private key is being read from e.g. environment variable

beeb commented 1 month ago

Thanks for the explanation! Could a fix potentially be to skip showing the prompts the second time around and reuse the values provided the first time?

beeb commented 1 month ago

Maybe it's simpler to invoke the script with -i 1 and not have the private key prompt in the script. Is there a way to detect if that argument is missing to e.g. revert inside the script if missing?

klkvr commented 1 month ago

Thanks for the explanation! Could a fix potentially be to skip showing the prompts the second time around and reuse the values provided the first time?

This could work, though it might result in unexpected edge cases in situations where prompts order is not deterministic, so its hard to come up with a generally working approach here

Maybe it's simpler to invoke the script with -i 1 and not have the private key prompt in the script. Is there a way to detect if that argument is missing to e.g. revert inside the script if missing?

if it will be missing, then script will just dry-run with default sender, and once you try to broadcast it will throw a error saying that script is missing sender, do you need some different behavior for this case?

beeb commented 1 month ago

@klkvr never mind my suggestion, the problem is the same with -i 1 added to the script command. It prompts twice.

klkvr commented 1 month ago

@klkvr never mind my suggestion, the problem is the same with -i 1 added to the script command. It prompts twice.

is the script still using vm.startBroadcast(vm.promptSecretUint("Enter the private key"))?

beeb commented 1 month ago

No I removed it since the -i 1 prompt does the same

beeb commented 1 month ago

Ok never mind I tried again and there is no double prompt with -i 1. I must have done something wrong. So the workaround would work.