如何使用web3py在Polygon链上转账ERC1155代币?
问题分析与解决方案
核心问题
你遇到的错误本质是用错了ABI:当前使用的是透明代理合约的ABI,里面只有代理相关的函数(比如upgradeTo、admin等),完全没有ERC1155代币的转账函数;另外你代码里调用的transfer也不是ERC1155标准的转账方法,ERC1155的标准转账函数是safeTransferFrom。
修正步骤
- 替换为ERC1155标准ABI:使用包含ERC1155核心函数的ABI,比如标准ERC1155的ABI(或者从PolygonScan上获取目标合约的完整ABI)。
- 调用正确的转账函数:ERC1155的标准转账函数是
safeTransferFrom,参数顺序为(from_address, to_address, token_id, amount, data)。 - 正确构建并签名交易:直接用
transact()需要本地节点解锁账户,更安全的方式是用私钥构建交易、签名后发送,同时指定Polygon网络的必要参数(gasPrice、nonce等)。
完整正确代码示例
from web3 import Web3 import json # Polygon RPC节点 rpc_polygon = "https://polygon-rpc.com" web3 = Web3(Web3.HTTPProvider(rpc_polygon)) # 配置你的账户信息 account_1 = "FROM_ADDRESS" # 替换为你的转出地址 account_2 = "TO_ADDRESS" # 替换为转入地址 private_key = "PRIVATE_KEY_HERE" # 替换为你的私钥 contract_address = "CONTRACT_ADDRESS" # 替换为目标ERC1155合约地址 token_id = 7 # 注意:TOKEN_ID是整数,不是字符串 transfer_amount = 1 # ERC1155的amount不需要转wei,直接填实际数量 # 1. 使用标准ERC1155 ABI(可以从PolygonScan获取目标合约的完整ABI替换这里) erc1155_abi = json.loads('''[ { "inputs": [ {"internalType": "address", "name": "_from", "type": "address"}, {"internalType": "address", "name": "_to", "type": "address"}, {"internalType": "uint256", "name": "_id", "type": "uint256"}, {"internalType": "uint256", "name": "_value", "type": "uint256"}, {"internalType": "bytes", "name": "_data", "type": "bytes"} ], "name": "safeTransferFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ {"internalType": "address", "name": "account", "type": "address"}, {"internalType": "uint256", "name": "id", "type": "uint256"} ], "name": "balanceOf", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function" } ]''') # 2. 初始化合约对象 checksum_contract = Web3.toChecksumAddress(contract_address) contract = web3.eth.contract(address=checksum_contract, abi=erc1155_abi) # 3. 获取必要的交易参数 nonce = web3.eth.get_transaction_count(account_1) gas_price = web3.eth.gas_price # 或者手动设置,比如web3.toWei("50", "gwei") # 4. 构建交易 txn = contract.functions.safeTransferFrom( account_1, account_2, token_id, transfer_amount, b"" # 额外数据,不需要就传空字节 ).buildTransaction({ 'chainId': 137, # Polygon主网链ID 'gas': 200000, # 预估gas,可根据实际调整 'gasPrice': gas_price, 'nonce': nonce, }) # 5. 用私钥签名交易 signed_txn = web3.eth.account.sign_transaction(txn, private_key=private_key) # 6. 发送交易并等待回执 txn_hash = web3.eth.send_raw_transaction(signed_txn.rawTransaction) txn_receipt = web3.eth.wait_for_transaction_receipt(txn_hash) # 7. 验证结果 print(f"交易哈希: {web3.toHex(txn_hash)}") if txn_receipt.status == 1: print("转账成功") # 可选:验证余额变化 balance = contract.functions.balanceOf(account_2, token_id).call() print(f"账户2的代币{token_id}余额: {balance}") else: print("转账失败")
关键细节说明
- ABI获取:如果目标合约是代理合约(比如你的原始ABI是代理的),需要在PolygonScan上找到合约的"Implementation"地址,获取该实现合约的ABI,而不是代理合约的ABI。
- ERC1155参数:
safeTransferFrom的最后一个参数_data是可选的额外数据,不需要的话传空字节b""即可。 - Gas设置:Polygon上的gas价格波动较大,你可以手动设置
gasPrice为当前网络的推荐值,比如用web3.toWei("50", "gwei")。 - Token ID类型:必须是整数,不能是字符串。
内容的提问来源于stack exchange,提问作者tripposters
相关产品推荐
相关产品推荐

