Skip to content

Conversation

@Syzygy106
Copy link
Contributor

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. Provide --yes flag to skip confirmation for non-interactive usage (scripts, CI/CD)

  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:

./target/debug/cast erc20 transfer \
  0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 \
  0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
  50000000000000000000 \
  --yes \
  --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

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

1 participant