Web3代币兑换触发TRANSFER_FROM_FAILED错误求助
问题
实现了两个Web3函数:一个将WBNB兑换为指定代币(buy函数),另一个将该代币换回WBNB(sell函数)。两者逻辑基本一致,仅兑换方向与amountIn的处理不同——buy函数对amountIn做了BNB单位转换,sell函数未做。执行sell函数时触发以下错误:
raise ContractLogicError(response['error']['message']) web3.exceptions.ContractLogicError: execution reverted: TransferHelper: TRANSFER_FROM_FAILED
sell函数代码:
token = "0x2859e4544C4bB03966803b044A93563Bd2D0DD4D" def sell(token, amountToSell): tokenToBuy = web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") # wbnb contract address spend = web3.toChecksumAddress(token) nonce = web3.eth.get_transaction_count(sender_address) pancakeswap2_txn = contractbuy.functions.swapExactTokensForTokens( amountToSell, #web3.toWei(amountToBuy, 'ether'), 0, [spend, tokenToBuy], sender_address, (int(time.time()) + 10000) ).buildTransaction({ 'from': sender_address, #'value': amountToSell, #'value': web3.toWei(amountToSell, 'ether'), # This is the Token(BNB) amount you want to Swap from 'gasPrice': web3.toWei('5', 'gwei'), 'nonce': nonce, }) signed_txn = web3.eth.account.sign_transaction(pancakeswap2_txn, private_key=privatekey) tx_token = web3.eth.send_raw_transaction(signed_txn.rawTransaction) transaction_tx = web3.toHex(tx_token) print("Sell was succesfull, sold: " + transaction_tx) return transaction_tx
buy函数代码:
def buy(token, amountToBuy): spend = web3.toChecksumAddress("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") # wbnb contract address tokenToBuy = web3.toChecksumAddress(token) nonce = web3.eth.get_transaction_count(sender_address) pancakeswap2_txn = contractbuy.functions.swapExactTokensForTokens( web3.toWei(amountToBuy, 'ether'), 0, # set to 0, or specify minimum amount of token you want to receive - consider decimals!!! [spend, tokenToBuy], sender_address, (int(time.time()) + 10000) ).buildTransaction({ 'from': sender_address, #'value': 1000, #'value': web3.toWei(amountToBuy, 'ether'), # This is the Token(BNB) amount you want to Swap from 'gasPrice': web3.toWei('5', 'gwei'), 'nonce': nonce, }) signed_txn = web3.eth.account.sign_transaction(pancakeswap2_txn, private_key=privatekey) tx_token = web3.eth.send_raw_transaction(signed_txn.rawTransaction) transaction_tx = web3.toHex(tx_token) print("succesfull, bought: " + transaction_tx) return transaction_tx
钱包中持有该代币与WBNB,但sell函数执行失败,buy函数可正常运行,不清楚问题所在。
解决方案
出现TransferHelper: TRANSFER_FROM_FAILED错误的核心原因是PancakeSwap合约没有权限从你的钱包划转要卖出的代币,加上你未处理代币小数位数导致参数错误,具体修复步骤如下:
给PancakeSwap合约授权代币划转权限
在执行sell交易前,必须调用目标代币的approve函数,允许PancakeSwap Router合约划转指定数量的代币。示例代码:# 标准ERC20代币ABI片段,可直接使用 token_abi = [{"constant":true,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] def approve_token(token_address, spender_address, amount): token_contract = web3.eth.contract(address=web3.toChecksumAddress(token_address), abi=token_abi) nonce = web3.eth.get_transaction_count(sender_address) approve_txn = token_contract.functions.approve( spender_address, amount ).buildTransaction({ 'from': sender_address, 'gasPrice': web3.toWei('5', 'gwei'), 'nonce': nonce, }) signed_txn = web3.eth.account.sign_transaction(approve_txn, private_key=privatekey) tx_hash = web3.eth.send_raw_transaction(signed_txn.rawTransaction) web3.eth.wait_for_transaction_receipt(tx_hash) print("授权成功") # 在sell函数调用前执行授权,spender_address填你的contractbuy(PancakeSwap Router)地址 approve_token(token, contractbuy.address, amount_to_sell_wei)处理代币的小数位数
不同代币的小数位数可能不是18位(和WBNB不同),不能直接用web3.toWei转换,需根据代币实际小数位数计算最小单位数量:def get_token_decimals(token_address): token_contract = web3.eth.contract(address=web3.toChecksumAddress(token_address), abi=token_abi) return token_contract.functions.decimals().call() # 获取目标代币小数位数 decimals = get_token_decimals(token) # 转换为最小单位数量 amount_to_sell_wei = int(amountToSell * (10 ** decimals))之后在
swapExactTokensForTokens中传入amount_to_sell_wei作为第一个参数。确认参数正确性
- 检查
amount_to_sell_wei不能超过钱包中该代币的实际余额(转换为最小单位后) - 确认路由数组
[spend, tokenToBuy]顺序正确(要卖出的代币在前,WBNB在后)
- 检查
内容的提问来源于stack exchange,提问作者Soma Juice
相关产品推荐
相关产品推荐

