Skip to content

Conversation

@Syzygy106
Copy link
Contributor

@Syzygy106 Syzygy106 commented Nov 8, 2025

Motivation

Closes #12402

Enhance UX and prevent accidental transfers with incorrect amounts. Users may misunderstand the token's decimal places and accidentally send far more (or less) tokens than intended.

Also, approve() requires identical feature, so I decided to add the same.

At the other hand, transferFrom() - doesn't need that, because this method is rarely called by users implicitly, more often him calls other smartcontracts (like swapRouter).

Solution

Added interactive confirmation prompts to cast erc20 transfer and cast erc20 approve commands that:

  1. Fetch token metadata (symbol and decimals) from the ERC20 contract

  2. Display human-readable amounts in the confirmation prompt:
    Example: Confirm transfer of 100 USDC to address 0x666...666 instead of raw 100000000

  3. Support non-interactive usage via stdin piping (e.g., yes | cast erc20 transfer ...)

  4. Handle edge cases gracefully:
    -Falls back to raw amount if decimals/symbol can't be fetched
    -Shows warning if token metadata is unavailable

Demonstration

Let's create a test token first:

forge create crates/cast/tests/fixtures/TestToken.sol:TestToken   --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80   --rpc-url http://localhost:8545   --broadcast

Then we can test behavior:

./target/debug/cast erc20 transfer   0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512   0x70997970C51812dc3A010C7d01b50e0d17dc79C8   100000000000000000000   --rpc-url http://localhost:8545   --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

---
Confirm transfer of 100 TEST to address 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 [y/n] 

In case y (yes):

Confirm transfer of 100 TEST to address 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 yes

---
0x6a6b22e5ff88c63d47527d7d8ff35c3d412388ba7392b1bbc6985f30ccf0e87c

In case n (no):

Confirm transfer of 100 TEST to address 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 no

---
Error: Transfer cancelled by user

With skip promt that would be:

yes | ./target/debug/cast erc20 transfer \
  0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 \
  0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
  50000000000000000000 \
  --rpc-url http://localhost:8545 \
  --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80


---

0x3de20e9150169dfe8e7a0c40ecbba21d99587337c3de52d864cd871ed431c0e7

In case where contract address aren't correct/contract doesn't support ERC20 interface for decimals/symbol, we'll get a warning:

./target/debug/cast erc20 transfer \
  0x1234567890123456789012345678901234567890 \
  0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
  100 \
  --rpc-url http://localhost:8545 \
  --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80


Warning: Warning: Could not fetch token metadata (decimals/symbol). The address may not be a valid ERC20 token contract.
Confirm transfer of 100 TOKEN (raw amount) to address 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 [y/n]

The same behavior has been added to approve():

./target/debug/cast erc20 approve \
  0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 \
  0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
  75000000000000000000 \
  --rpc-url http://localhost:8545 \
  --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Confirm approval for 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 to spend 75 TEST from your account [y/n]

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

@Syzygy106
Copy link
Contributor Author

Also, I would like to update Foundry book, according to a new flag

Copy link
Collaborator

@grandizzy grandizzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, left a comment re new arg, don't think we need it?

@Syzygy106 Syzygy106 requested a review from grandizzy November 16, 2025 15:05
@grandizzy grandizzy changed the title Feat/cast erc20 safe preflight feat(cast): erc20 safe preflight Nov 18, 2025
@Syzygy106
Copy link
Contributor Author

Hmmm, CI / deny fails. But looks like it isn't my fault

Copy link
Collaborator

@grandizzy grandizzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, left comment, pls check

@Syzygy106 Syzygy106 requested a review from grandizzy November 19, 2025 12:15
Copy link
Contributor

@onbjerg onbjerg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know you can pipe in yes, but let's also add a --yes/-y as this is pretty common for clis

@Syzygy106
Copy link
Contributor Author

i know you can pipe in yes, but let's also add a --yes/-y as this is pretty common for clis

Hi there, @onbjerg , I actually agree with the --yes flag approach - that was my initial implementation (you can see it in the PR history above - #12499 (comment)).

However, other maintainers had different perspectives:

  1. @grandizzy (the original issue author) suggested removing the --yes flag, saying "don't think we need it?" feat(cast): erc20 safe preflight #12499 (comment)
  2. @0xrusowsky also seemed to prefer the pipe approach feat(cast): erc20 safe preflight #12499 (comment)

Their reasoning was avoiding adding new arguments to keep the CLI simpler and easier to maintain and following Unix philosophy with yes | pipe being a standard pattern.

I'm happy to implement either approach, but before making changes again, I think it would be helpful if the maintainers could align on the preferred solution:

Option 1: --yes/-y flag (more explicit, common in modern CLIs) (I prefer this)
Option 2: yes | pipe only (Unix philosophy, no new flags)

@grandizzy @0xrusowsky @onbjerg - could you please discuss and let me know which direction you'd like me to take? I want to make sure we're all aligned before implementing the final version.

Other maintainers are also invited to the conversation @mattsse , @zerosnacks , @DaniPopes

@Syzygy106 Syzygy106 requested a review from onbjerg November 20, 2025 23:27
@grandizzy
Copy link
Collaborator

@Syzygy106 sorry for back and forth, we'll discuss and make a final call re how to add this. thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

feat(cast): ask for confirmation on erc20-token transfer

4 participants