Sending ERC-20 tokens programmatically is a foundational skill for any Ethereum developer. Whether you're building decentralized applications, automating token transfers, or integrating blockchain functionality into your backend systems, understanding how to interact with ERC-20 smart contracts using Python and Web3.py is essential.
This comprehensive guide walks you through the process of sending ERC-20 tokens and granting token approvals to smart contracts—two of the most common operations in Web3 development.
Understanding ERC-20 Tokens and Approvals
ERC-20 is the most widely adopted token standard on Ethereum. It defines a set of rules that all fungible tokens must follow, enabling seamless integration across wallets, exchanges, and decentralized applications (dApps). Key functions include transfer, balanceOf, and approve, which allow users to move tokens and authorize third-party access.
The approve function is particularly important when interacting with DeFi protocols. Instead of transferring tokens directly to a smart contract, you grant it permission to withdraw a specified amount from your wallet—enhancing security and control.
👉 Learn how to securely manage token approvals and transfers with advanced tools.
Setting Up Your Development Environment
Before writing code, ensure your environment is ready for Ethereum interaction.
Prerequisites
- Basic knowledge of Ethereum and smart contracts
- Python 3.9+ installed on your system
- A code editor like VS Code
- An EVM-compatible wallet (e.g., MetaMask) with private key access
- Access to an Ethereum node via a service like QuickNode or a local node
While you can run your own node, using a reliable node provider ensures faster response times and consistent uptime—critical for production applications.
Required Dependencies
| Dependency | Version |
|---|---|
| Python | 3.9.6 |
| web3.py | 6.18.0 |
Install Web3.py using pip:
pip install web3Ensure your environment is clean and dependencies are up to date to avoid installation issues.
Creating a Web3 Connection Endpoint
To interact with the Ethereum blockchain, you need an RPC (Remote Procedure Call) endpoint. While public nodes are available, they often suffer from latency and rate limiting.
Using a dedicated node service ensures stable connectivity. For this tutorial, we'll use the Ethereum Sepolia testnet, but the same principles apply to mainnets and other EVM-compatible chains like Polygon, Arbitrum, or Base.
Once your endpoint is created, copy the HTTPS RPC URL—you’ll use it in your Python script to connect to the network.
Funding Your Test Wallet
To perform transactions on the Sepolia network, your wallet needs ETH to cover gas fees.
Use the QuickNode Multi-Chain Faucet or similar services to request test ETH. Simply connect your wallet or enter your address. Note: some faucets require a small mainnet ETH balance (e.g., 0.001 ETH) for spam prevention.
With test funds in place, you're ready to start coding.
Sending ERC-20 Tokens via Web3.py
Now let’s implement a script to send ERC-20 tokens using Python and Web3.py.
Step 1: Project Setup and Configuration
Create a new file named main.py and begin by importing necessary modules:
from web3 import Web3
from web3.middleware import geth_poa_middleware
import jsonStep 2: Configure Connection and Contract Details
Update the following placeholders with your actual values:
RPC_URL = 'YOUR_QUICKNODE_ENDPOINT'
CONTRACT_ADDRESS = Web3.to_checksum_address('ERC20_CONTRACT_ADDRESS')
TO_ADDRESS = 'RECIPIENT_ADDRESS'
private_key = 'YOUR_PRIVATE_KEY'
if not private_key:
raise ValueError("Private key not provided.")
w3 = Web3(Web3.HTTPProvider(RPC_URL))
w3.middleware_onion.inject(geth_poa_middleware, layer=0)
if not w3.is_connected():
raise ConnectionError("Failed to connect to Ethereum network")For Proof-of-Authority (PoA) networks like Sepolia, injecting geth_poa_middleware ensures proper transaction handling.
Step 3: Load Contract ABI and Build Transaction
You’ll need the ABI (Application Binary Interface) of the ERC-20 token contract. If the contract is verified on Etherscan, you can copy it from the "Contract" tab.
Save it as abi.json in your project directory:
with open('abi.json') as abi_file:
contract_abi = json.load(abi_file)
contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=contract_abi)
token_amount = w3.to_wei(1, 'ether') # Adjust amount as needed
nonce = w3.eth.get_transaction_count(w3.eth.account.from_key(private_key).address)
transaction = contract.functions.transfer(TO_ADDRESS, token_amount).build_transaction({
'chainId': w3.eth.chain_id,
'gas': 2000000,
'gasPrice': w3.eth.gas_price,
'nonce': nonce,
})Step 4: Sign and Send the Transaction
signed_txn = w3.eth.account.sign_transaction(transaction, private_key)
try:
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
print(f"Transaction sent! Hash: {tx_hash.hex()}")
except Exception as e:
print(f"Error sending transaction: {e}")Run the script:
python main.pyOn success, you’ll see output like:
Transaction sent! Hash: 0x9fc4ea7be48f5af020e257023e5e56c28246fe3d54c815bc5b623e45d5ef1aabYou can view the transaction on Sepolia Etherscan.
👉 Explore more powerful ways to automate blockchain interactions with secure APIs.
Granting Token Approval to Smart Contracts
Sometimes, instead of sending tokens directly, you want to allow a smart contract to spend them on your behalf—common in DeFi swaps or staking.
Use the approve function:
spender_address = Web3.to_checksum_address('CONTRACT_TO_APPROVE')
token_amount = w3.to_wei(1, 'ether')
approval_tx = contract.functions.approve(spender_address, token_amount).build_transaction({
'chainId': w3.eth.chain_id,
'gas': 2000000,
'nonce': nonce + 1, # Increment nonce after previous transaction
})
signed_approval = w3.eth.account.sign_transaction(approval_tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_approval.rawTransaction)
print(f"Approval transaction sent! Hash: {tx_hash.hex()}")Now the designated contract can withdraw up to the approved amount using transferFrom.
Frequently Asked Questions
Q: What is an ERC-20 token?
A: ERC-20 is a technical standard for fungible tokens on Ethereum, defining methods like transfer, balanceOf, and approve to ensure interoperability across platforms.
Q: Why do I need to approve before transferring tokens to a contract?
A: Approval gives a smart contract permission to spend your tokens without holding them outright. This reduces risk—if compromised, only the approved amount is accessible.
Q: Can I use this method on other blockchains?
A: Yes! Any EVM-compatible chain (e.g., Polygon, BSC, Arbitrum) supports ERC-20 tokens and Web3.py interactions with minor configuration changes.
Q: Is it safe to use my private key in code?
A: For production apps, never hardcode private keys. Use environment variables or secure key management solutions like hardware wallets or vaults.
Q: How do I get a contract’s ABI?
A: Verified contracts on Etherscan provide downloadable ABIs under the "Contract" tab. For unverified contracts, you may need to compile the source code or find official documentation.
Q: What happens if I run out of gas?
A: The transaction fails and gas is consumed. Always estimate gas usage beforehand using estimate_gas() and keep sufficient ETH balance.
👉 Securely manage your digital assets while developing blockchain applications.
Final Thoughts
You’ve now learned how to send ERC-20 tokens and approve smart contracts using Web3.py—a crucial skill for any blockchain developer. These techniques form the backbone of wallet integrations, automated trading bots, and DeFi platforms.
As you advance, consider exploring additional features like event listening, batch transactions, and error handling for robust applications.
Stay curious, keep experimenting, and continue expanding your Web3 toolkit. The future of decentralized technology is being built one line of code at a time.