Foundry tools: Cast
TL;DR: Cast is Foundry's command-line tool for interacting with Ethereum smart contracts and nodes. Key features include: number format conversions (decimal/hex), reading contract state with cast call, writing transactions with cast send, and secure private key management via encrypted keystore. Supports RPC configuration through CLI flags, environment variables, or foundry.toml.
Foundry is the most relevant and used frameworks nowadays to work with smart contracts in Solidity. Foundry provides a set of tools to facilitate the development, testing, and deployment of smart contracts. One of these tools is Cast.
Cast is a command-line tool that allows you to interact with Ethereum nodes and smart contracts. It provides a variety of commands to perform different tasks, such as sending transactions, querying contract state, making data conversions, and more. In this post, we will explore some examples of how to use Cast in real-world scenarios.
Cast examples
In this section, we will see some practical examples of how to use Cast for different purposes, such as number conversion, reading smart contract values, writing smart contract values and handle private keys.
If you want to copy the commands, just click on the command box and it will be copied to your clipboard.Number decimal - hexadecimal conversion
One of the simplest use cases of Cast is to convert numbers between decimal and hexadecimal formats. Used especially when dealing with smart contract data.
cast to-dec 0x000000000000000000000000000000000000000000000000000000000000002a
cast to-hex 50Those are just two simple examples, but Cast supports many other conversions, such as to-bool, to-address, to-bytes32, etc.
Call smart contracts to read values
One of the most common use cases of Cast is to call smart contract functions to read data from the blockchain. It permits easyly querying contract state without needing to write any code.
The aspects that must be considered are:
- The contract address: The address of the smart contract you want to interact with.
- The function signature: The signature of the function you want to call.
- The network RPC URL: The URL of the Ethereum node you want to connect to. You can include directly in the cast service, you can read from .env file or you can configure it in the foundry.toml file.
cast call [contract_address] "number()" --rpc-url [network_rpc_url]
In this second example, we are calling the allowance function of an ERC20 token contract to check the allowance that an address has given to another address. The main differece with the previous example is that this function requires two parameters: the owner address and the spender address. Furthermore, in this case we are passing the response type (uint256).
cast call [contract_address] "allowance(address, address)(uint256)" [param1] [param2] --rpc-url [network_rpc_url]
Write smart contracts to update values
Another important use case of Cast is to send transactions to smart contracts to update their state. This allows you to interact with contracts and modify their data.
When sending transactions, you need to consider:
- The private key: The private key of the account you want to use to sign the transaction.
- The contract address: The address of the smart contract you want to interact with.
- The function signature: The signature of the function you want to call.
- The network RPC URL: The URL of the Ethereum node you want to connect to. You can include directly in the cast service, you can read from .env file or you can configure it in the foundry.toml file.
In this example, we are calling the mint function of an ERC20 token contract to mint new tokens to a specific address. The function requires two parameters: the recipient address and the amount of tokens to mint.
cast send --private-key $PRIVATE_KEY [contract_address] "mint(address,uint256)" [param1] [param2] --rpc-url $RPC_URL
In this second example, we are using the cast parse-units command to convert a human-readable token amount (5 tokens) into its corresponding smallest unit (wei for Ether or the token's smallest denomination). This is particularly useful when dealing with ERC20 tokens that have decimals.
cast send --private-key $PRIVATE_KEY [contract_address] "mint(address,uint256)" [param1] $(cast parse-units 5) --rpc-url $RPC_URL
Handle private keys and addresses
Cast also provides commands to handle private keys securely. To understand the importance of this, we must understand that in production environments, private keys should never be hardcoded, exposed in the code or even included in a .env file. Instead, they should be managed securely using the keystore.
The keystore is a secure storage mechanism that encrypts private keys and protects them with a password. To store a private key in the keystore, you can use the following command:
cast wallet import [key_name] --interactive
This command will prompt a interactve input in your terminal and you must to paste there the private key you want to store.
To see the list of private keys you have stored there, use:
cast wallet list
To use a private key stored in the keystore, for running a script you can use:
forge script script/general/DeploySimpleTest.s.sol --fork-url [rpc_url] --account [key_name] --sender [address_corresponding_to_pk] --broadcast
This command will use the private key associated with the specified key name to sign the transactions.
Frequently Asked Questions
What is Cast used for?
Cast is a command-line tool from the Foundry toolkit used for interacting with Ethereum nodes and smart contracts. It enables reading contract data, sending transactions, converting data formats, and managing private keys without writing code.
How do I read data from a smart contract using Cast?
Use the cast call command with the contract address, function signature, and RPC URL. Example: cast call 0x123... "balanceOf(address)(uint256)" 0xabc... --rpc-url $RPC_URL
What's the difference between cast call and cast send?
cast call is for read-only operations that don't modify blockchain state and don't require gas. cast send is for state-changing transactions that require a private key, consume gas, and modify contract data.
How do I convert hexadecimal to decimal with Cast?
Use cast to-dec 0x1a to convert hex to decimal, or cast to-hex 26 to convert decimal to hex. Cast supports many format conversions including to-bytes32, to-address, and to-bool.
How should I handle private keys with Cast?
Never hardcode private keys in scripts or .env files for production. Use Cast's encrypted keystore with cast wallet import [key_name] --interactive to securely store keys protected by a password.
How do I use a keystore private key in Cast commands?
Reference the stored key using --account [key_name] in your commands. For Forge scripts, add --account [key_name] --sender [address] flags instead of --private-key.
Can Cast work with any Ethereum network?
Yes, Cast works with any EVM-compatible network including Ethereum mainnet, testnets (Sepolia, Goerli), L2s (Arbitrum, Optimism, Polygon), and local nodes like Anvil. Specify the network via --rpc-url parameter.
How do I pass function parameters with Cast?
Include parameters after the function signature in order. Example: cast call 0x123... "allowance(address,address)(uint256)" 0xOwner... 0xSpender... --rpc-url $RPC_URL
What is cast parse-units used for?
cast parse-units converts human-readable token amounts into their smallest unit (wei). For example, cast parse-units 5 converts 5 tokens to 5000000000000000000 wei, accounting for 18 decimals.
Do I need to specify return types in Cast function signatures?
For cast call (read operations), specifying return types like (uint256) helps Cast properly decode and display the response. For cast send (write operations), return types are typically not needed.
Extra resources
If you want to learn more about Cast and its capabilities, you can check the official documentation at Cast official docs