转账ERC20代币失败:web3.exceptions.ContractLogicError:执行恢复:ERC20:从零地址转账

Posted

技术标签:

【中文标题】转账ERC20代币失败:web3.exceptions.ContractLogicError:执行恢复:ERC20:从零地址转账【英文标题】:Transfer ERC20 Token Failed: web3.exceptions.ContractLogicError: execution reverted: ERC20: transfer from the zero address 【发布时间】:2021-08-06 06:55:18 【问题描述】:

所以我尝试使用转账功能与 ERC20 智能合约进行交互,它完美运行下面的示例将扣除第一个账户的 ERC20 代币余额并将其添加到第二个账户的 ERC20 代币余额中。

import json

from web3 import Web3
from web3.middleware import geth_poa_middleware

if __name__ == "__main__":
    w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545', request_kwargs='timeout': 60))
    w3.middleware_onion.inject(geth_poa_middleware, layer=0)
    print(w3.clientVersion)

    first_account = w3.eth.accounts[0]
    fist_account = w3.toChecksumAddress(first_account)
    print(first_account)

    first_account_ether_balance = w3.eth.get_balance(first_account)
    print(f"ether balance for first_account is first_account_ether_balance")

    ABI = '["constant":true,"inputs":[],"name":"name","outputs":["name":"","type":"string"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":["name":"_upgradedAddress","type":"address"],"name":"deprecate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":false,"inputs":["name":"_spender","type":"address","name":"_value","type":"uint256"],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":[],"name":"deprecated","outputs":["name":"","type":"bool"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":["name":"_evilUser","type":"address"],"name":"addBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":[],"name":"totalSupply","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":["name":"_from","type":"address","name":"_to","type":"address","name":"_value","type":"uint256"],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":[],"name":"upgradedAddress","outputs":["name":"","type":"address"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":["name":"","type":"address"],"name":"balances","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"decimals","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"maximumFee","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"_totalSupply","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":["name":"_maker","type":"address"],"name":"getBlackListStatus","outputs":["name":"","type":"bool"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":["name":"","type":"address","name":"","type":"address"],"name":"allowed","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"paused","outputs":["name":"","type":"bool"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":["name":"who","type":"address"],"name":"balanceOf","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":[],"name":"getOwner","outputs":["name":"","type":"address"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"owner","outputs":["name":"","type":"address"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"symbol","outputs":["name":"","type":"string"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":["name":"_to","type":"address","name":"_value","type":"uint256"],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":false,"inputs":["name":"newBasisPoints","type":"uint256","name":"newMaxFee","type":"uint256"],"name":"setParams","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":false,"inputs":["name":"amount","type":"uint256"],"name":"issue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":false,"inputs":["name":"amount","type":"uint256"],"name":"redeem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":["name":"_owner","type":"address","name":"_spender","type":"address"],"name":"allowance","outputs":["name":"remaining","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":[],"name":"basisPointsRate","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":true,"inputs":["name":"","type":"address"],"name":"isBlackListed","outputs":["name":"","type":"bool"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":["name":"_clearedUser","type":"address"],"name":"removeBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":true,"inputs":[],"name":"MAX_UINT","outputs":["name":"","type":"uint256"],"payable":false,"stateMutability":"view","type":"function","constant":false,"inputs":["name":"newOwner","type":"address"],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","constant":false,"inputs":["name":"_blackListedUser","type":"address"],"name":"destroyBlackFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","inputs":["name":"_initialSupply","type":"uint256","name":"_name","type":"string","name":"_symbol","type":"string","name":"_decimals","type":"uint256"],"payable":false,"stateMutability":"nonpayable","type":"constructor","anonymous":false,"inputs":["indexed":false,"name":"amount","type":"uint256"],"name":"Issue","type":"event","anonymous":false,"inputs":["indexed":false,"name":"amount","type":"uint256"],"name":"Redeem","type":"event","anonymous":false,"inputs":["indexed":false,"name":"newAddress","type":"address"],"name":"Deprecate","type":"event","anonymous":false,"inputs":["indexed":false,"name":"feeBasisPoints","type":"uint256","indexed":false,"name":"maxFee","type":"uint256"],"name":"Params","type":"event","anonymous":false,"inputs":["indexed":false,"name":"_blackListedUser","type":"address","indexed":false,"name":"_balance","type":"uint256"],"name":"DestroyedBlackFunds","type":"event","anonymous":false,"inputs":["indexed":false,"name":"_user","type":"address"],"name":"AddedBlackList","type":"event","anonymous":false,"inputs":["indexed":false,"name":"_user","type":"address"],"name":"RemovedBlackList","type":"event","anonymous":false,"inputs":["indexed":true,"name":"owner","type":"address","indexed":true,"name":"spender","type":"address","indexed":false,"name":"value","type":"uint256"],"name":"Approval","type":"event","anonymous":false,"inputs":["indexed":true,"name":"from","type":"address","indexed":true,"name":"to","type":"address","indexed":false,"name":"value","type":"uint256"],"name":"Transfer","type":"event","anonymous":false,"inputs":[],"name":"Pause","type":"event","anonymous":false,"inputs":[],"name":"Unpause","type":"event"]'
    ABI = json.loads(ABI)

    second_account = "0x2ee7304bad7c1aef6292f1e70124e77370007924"
    second_account = w3.toChecksumAddress(second_account)
    ether_balance_second_account = w3.eth.get_balance(second_account)
    print(f"ether balance for second_account is ether_balance_second_account")

    gldd_contract_address = "0xe9814432a38b18d0730b9e0e277eab759b6019d7"
    contract_address = w3.toChecksumAddress(gldd_contract_address)
    gldd_goerli_contract = w3.eth.contract(contract_address, abi=ABI)

    contract_name = gldd_goerli_contract.functions.name().call()
    print(f"Contract name is contract_name")

    contract_symbol = gldd_goerli_contract.functions.symbol().call()
    print(f"Contract symbol is contract_symbol")

    decimals = gldd_goerli_contract.functions.decimals().call()
    DECIMALS = 10 ** decimals

    # total_supply = gldd_goerli_contract.functions.totalsupply().call()
    # print(f"Total supply total_supply")

    first_account_gldd_balance = gldd_goerli_contract.functions.balanceOf(first_account).call()
    print(f"First account GLDD balance first_account_gldd_balance")

    second_account_gldd_balance = gldd_goerli_contract.functions.balanceOf(second_account).call()
    print(f"Second account GLDD balance second_account_gldd_balance")

    # print("Trying to send GLDD the first way")
    # transaction = 
        # 'from': first_account,
        # 'to': second_account,
        # 'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(first_account)),
        # 'gas': 1000000,
        # "gasPrice": w3.eth.gas_price,
        # 'data' : gldd_goerli_contract.caller.transfer(Web3.toChecksumAddress(second_account), 100),
    # 
    # tx_hash = w3.eth.send_transaction(transaction)
    # tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
    # print(tx_receipt)

    print("Trying to send GLDD the second way")
    tx_hash = gldd_goerli_contract.functions.transfer(second_account, 1000).transact('from': first_account)
    tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
    print(tx_receipt)

    first_account_gldd_balance = gldd_goerli_contract.functions.balanceOf(first_account).call()
    print(f"First account GLDD balance first_account_gldd_balance")

    second_account_gldd_balance = gldd_goerli_contract.functions.balanceOf(second_account).call()
    print(f"Second account GLDD balance second_account_gldd_balance")

现在,如果我为第一笔交易发表评论

    # print("Trying to send GLDD the first way")
    # transaction = 
        # 'from': first_account,
        # 'to': second_account,
        # 'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(first_account)),
        # 'gas': 1000000,
        # "gasPrice": w3.eth.gas_price,
        # 'data' : gldd_goerli_contract.caller.transfer(Web3.toChecksumAddress(second_account), 100),
    # 
    # tx_hash = w3.eth.send_transaction(transaction)
    # tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
    # print(tx_receipt)

事务似乎因错误web3.exceptions.ContractLogicError: execution reverted: ERC20: transfer from the zero address 而失败。 有谁知道这里发生了什么?我想知道这个错误背后的原因。

【问题讨论】:

【参考方案1】:

我刚刚发现错误,您需要将第一笔交易记录如下

    print("Trying to send GLDD the first way")
    transaction = 
        'from': first_account,
        'to': second_account,
        # 'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(first_account)),
        'gas': 2000000,
        'gasPrice': w3.eth.gas_price,
        'value': "0x0",
        'data' : gldd_goerli_contract.functions.transfer(second_account, 1000).transact('from': first_account),
    
    tx_hash = w3.eth.send_transaction(transaction)
    tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
    print(tx_receipt)

【讨论】:

以上是关于转账ERC20代币失败:web3.exceptions.ContractLogicError:执行恢复:ERC20:从零地址转账的主要内容,如果未能解决你的问题,请参考以下文章

,让你了解ERC-1155 多代币标准协议

为部署在 RinkeBy 测试网上的智能合约执行 ERC20 代币“传输函数”的原始交易

ERC20 代币转移到智能合约

第77篇 ERC20-USDT智能合约

发送 ERC-20 令牌失败。交易成功,但没有发送令牌

以太坊 USDT-ERC20合约 注释版