From 214dba74e04d9f051eb97cfd870cf632a098da0d Mon Sep 17 00:00:00 2001 From: Yotam Bar-On Date: Sat, 23 Mar 2024 02:51:02 +0200 Subject: [PATCH] docs: document vm.prompt (#1151) --- src/SUMMARY.md | 1 + src/cheatcodes/external.md | 1 + src/cheatcodes/prompt.md | 109 ++++++++++++++++++++++++++++++++ src/reference/config/testing.md | 8 +++ 4 files changed, 119 insertions(+) create mode 100644 src/cheatcodes/prompt.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index f4de0a4bd..99f04ed8a 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -419,6 +419,7 @@ - [`transact`](./cheatcodes/transact.md) - [External](./cheatcodes/external.md) - [`ffi`](./cheatcodes/ffi.md) + - [`prompt`](./cheatcodes/prompt.md) - [`projectRoot`](./cheatcodes/project-root.md) - [`getCode`](./cheatcodes/get-code.md) - [`getDeployedCode`](./cheatcodes/get-deployed-code.md) diff --git a/src/cheatcodes/external.md b/src/cheatcodes/external.md index ea0e19b9a..397b76417 100644 --- a/src/cheatcodes/external.md +++ b/src/cheatcodes/external.md @@ -1,6 +1,7 @@ ## External - [`ffi`](./ffi.md) +- [`prompt`](./prompt.md) - [`projectRoot`](./project-root.md) - [`getCode`](./get-code.md) - [`getDeployedCode`](./get-deployed-code.md) diff --git a/src/cheatcodes/prompt.md b/src/cheatcodes/prompt.md new file mode 100644 index 000000000..b7065f8a8 --- /dev/null +++ b/src/cheatcodes/prompt.md @@ -0,0 +1,109 @@ +## `prompt` + +### Signature + +```solidity +function prompt(string calldata promptText) external returns (string memory input); +function promptSecret(string calldata promptText) external returns (string memory input); +``` + +### Description + +Display an interactive prompt to the user for inserting arbitrary data. + +`vm.prompt` displays an interactive input, while `vm.promptSecret` displays a +hidden input, used for passwords and other secret information that should not +leak to the terminal. + +> ℹ️ **Note** +> +> This cheatcode is meant to be used in scripts ― not tests. It is also advised to +> follow the best practices below for testing scripts that use `vm.prompt` and +> handling timeouts, since scripts might otherwise hang or revert. This cheatcode +> reverts when running in a non-interactive shell. + +### Configuration + +In order to prevent unwanted hangups, `vm.prompt` has a timeout configuration. + +In your `foundry.toml`: + +```toml +prompt_timeout = 120 +``` + +Default value is `120` and values are in seconds. + +### Best practices + +#### Testing scripts that use `vm.prompt` + +When testing scripts containing `vm.prompt` it is recommended to use the +following pattern: + +```solidity +contract Script { + function run() public { + uint256 myUint = vm.parseUint(vm.prompt("enter uint")); + run(myUint); + } + + function run(uint256 myUint) public { + // actual logic + } +} +``` + +That way, we are keeping the UX gain (don't have to provide `--sig` argument +when running the script), but tests can set any value to `myUint` and not just +a hardcoded default. + +#### Handling timeouts + +When a user fails to provide an input before the timeout expires, the +`vm.prompt` cheatcode reverts. If you'd like, timeouts can be handled by using +`try/catch`: + +```solidity +string memory input; + +try vm.prompt("Username") returns (string memory res) { + input = res; +} +catch (bytes memory) { + input = "Anonymous"; +} +``` + +### Examples + +#### Choose RPC endpoint + +Provide an option to choose the RPC/chain to run on. + +In your `foundry.toml` file: + +```toml +[rpc_endpoints] +mainnet = "https://eth.llamarpc.com" +polygon = "https://polygon.llamarpc.com" +``` + +In your script: + +```solidity +string memory rpcEndpoint = vm.prompt("RPC endpoint"); +vm.createSelectFork(rpcEndpoint); +``` + +#### Parse user input into native types + +We can use the string parsing cheatcodes to parse the responses from users: + +```solidity +uint privateKey = uint(vm.parseBytes32(vm.promptSecret("Private key"))); +address to = vm.parseAddress(vm.prompt("Send to")); +uint amount = vm.parseUint(vm.prompt("Amount (wei)")); +vm.broadcast(privateKey); +payable(to).transfer(amount); +``` diff --git a/src/reference/config/testing.md b/src/reference/config/testing.md index 996161ea1..845f4451d 100644 --- a/src/reference/config/testing.md +++ b/src/reference/config/testing.md @@ -300,6 +300,14 @@ optimism = "https://optimism.alchemyapi.io/v2/..." mainnet = "${RPC_MAINNET}" ``` +##### `prompt_timeout` + +- Type: integer +- Default: 120 +- Environment: `FOUNDRY_PROMPT_TIMEOUT` + +The number of seconds to wait before `vm.prompt` reverts with a timeout. + ### Fuzz Configuration values for `[fuzz]` section.