## `ffi`

### Signature

```solidity
function ffi(string[] calldata commandInput) external returns (bytes memory result);
```

### Description

Calls an arbitrary command if [`ffi`](/config/reference/testing#ffi) is enabled.

It is generally advised to use this cheatcode as a last resort, and to not enable it by default, as anyone who can change the tests of a project will be able to execute arbitrary commands on devices that run the tests.

### Parameters

| Parameter      | Type       | Description                        |
|----------------|------------|------------------------------------|
| `commandInput` | `string[]` | The command and arguments to execute |

### Returns

| Type    | Description                                    |
|---------|------------------------------------------------|
| `bytes` | The output of the command as bytes             |

### Examples

ABI encoded output:

```solidity [test/FFI.t.sol]
string[] memory inputs = new string[](3);
inputs[0] = "echo";
inputs[1] = "-n";
// ABI encoded "gm", as a hex string
inputs[2] = "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002676d000000000000000000000000000000000000000000000000000000000000";

bytes memory res = vm.ffi(inputs);
string memory output = abi.decode(res, (string));
assertEq(output, "gm");
```

UTF8 string output:

```solidity [test/FFI.t.sol]
string[] memory inputs = new string[](3);
inputs[0] = "echo";
inputs[1] = "-n";
inputs[2] = "gm";

bytes memory res = vm.ffi(inputs);
assertEq(string(res), "gm");
```

### Gotchas

:::warning
By default the `ffi` cheatcode assumes the output of the command is a hex encoded value (e.g. a hex string of an ABI encoded value). If hex decoding fails, it will return the output as UTF8 bytes that you can cast to a string.
:::

:::note
The script will be executed from the top-level directory of your project, not inside `test` or any other subdirectory.
:::

:::warning[Output Formatting]
Make sure that the output does not include a `\n` newline character. For example, in Rust use `print!` instead of `println!`.
:::

:::warning[Empty Array Elements]
Make sure that the inputs array does not have empty elements. They will be handled as inputs by the script, instead of being treated as whitespace.
:::

:::note[Windows Compatibility]
On Windows, some commands like `npm` or `npx` fail to execute with "program not found" error message. To avoid this, make sure the command contains the file extension as well, like `npm.cmd` or `npx.cmd`. These commands can be configured and read as environment variables so tests don't need to be changed when running on different operating systems.
:::

### Tips

* Use the cheatcode `toString` to easily convert arbitrary data to strings, so that you can pass them as command-line arguments.

### Related Cheatcodes

* [`projectRoot`](/reference/cheatcodes/project-root) - Returns the root directory of the project
* [`envString`](/reference/cheatcodes/env-string) - Read environment variables for cross-platform command configuration
