prompt

签名

function prompt(string calldata promptText) external returns (string memory input);
function promptSecret(string calldata promptText) external returns (string memory input);
function promptSecretUint(string calldata promptText) external returns (uint256);

描述

向用户显示一个交互式提示,以插入任意数据。

vm.prompt 显示一个交互式输入,而 vm.promptSecretvm.promptSecretUint 显示一个隐藏输入,用于密码和其他不应泄露到终端的秘密信息。

ℹ️ 注意

此作弊码旨在用于脚本中——而不是测试中。还建议遵循以下最佳实践,以测试使用 vm.prompt 的脚本并处理超时,因为脚本可能会挂起或回滚。此作弊码在非交互式 shell 中运行时会回滚。

配置

为了防止不必要的挂起,vm.prompt 有一个超时配置。

在你的 foundry.toml 中:

prompt_timeout = 120

默认值为 120,单位为秒。

最佳实践

测试使用 vm.prompt 的脚本

在测试包含 vm.prompt 的脚本时,建议使用以下模式:

contract Script {
    function run() public {
        uint256 myUint = vm.parseUint(vm.prompt("enter uint"));
        run(myUint);
    }

    function run(uint256 myUint) public {
        // actual logic
    }
}

这样,我们可以保持用户体验的提升(在运行脚本时不必提供 --sig 参数),但测试可以将任何值设置为 myUint,而不仅仅是硬编码的默认值。

处理超时

当用户未能在超时到期之前提供输入时,vm.prompt 作弊码会回滚。如果需要,可以通过使用 try/catch 来处理超时:

string memory input;

try vm.prompt("Username") returns (string memory res) {
    input = res;
}
catch (bytes memory) {
    input = "Anonymous";
}

示例

选择 RPC 端点

提供选择要运行的 RPC/链的选项。

在你的 foundry.toml 文件中:

[rpc_endpoints]
mainnet = "https://eth.llamarpc.com"
polygon = "https://polygon.llamarpc.com"

在你的脚本中:

string memory rpcEndpoint = vm.prompt("RPC endpoint");
vm.createSelectFork(rpcEndpoint);

将用户输入解析为原生类型

我们可以使用字符串解析作弊码来解析用户的响应:

uint privateKey = vm.promptSecretUint("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);