繁体   English   中英

如何检测以太坊地址是否为 ERC20 代币合约?

[英]How to detect if an Ethereum address is an ERC20 token contract?

如果我只从输入中得到一个以太坊地址,有没有办法找出它是否符合ERC20 代币标准?

有许多可能的方法来实现这一目标。 一种可能的快速和肮脏的解决方案是通过调用以下内容来检查合同地址上是否存在ERC20功能:

eth.call({to:contractAddress, data:web3.sha3("balanceOf(address)")})

非ERC20会返回一个“空” 0x六角响应,而一个ERC20会给你一个32字节uint ,在这种情况下0,但如果你的数据提供了一个地址,然后它会给你该地址的实际令牌平衡。

这不是保证合同是ERC20的保证方式,因为其他合同可能会暴露相同的功能,但这是一个快速简便的检查。 您可以在totalSupply()等上添加其他调用以获得更多确认。

ERC165解决了这个问题,但不幸的是,大多数ERC20实现都不支持它(截至2018年11月,至少OpenZeppelin 没有 )。 这意味着你可以尝试调用supportsInterface函数,但无论如何它都会恢复,你宁可复杂化。

不过,这里是它在ERC721中的定义:

bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd;
/*
 * 0x80ac58cd ===
 *   bytes4(keccak256('balanceOf(address)')) ^
 *   bytes4(keccak256('ownerOf(uint256)')) ^
 *   bytes4(keccak256('approve(address,uint256)')) ^
 *   bytes4(keccak256('getApproved(uint256)')) ^
 *   bytes4(keccak256('setApprovalForAll(address,bool)')) ^
 *   bytes4(keccak256('isApprovedForAll(address,address)')) ^
 *   bytes4(keccak256('transferFrom(address,address,uint256)')) ^
 *   bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^
 *   bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)'))
 */

虽然并不能保证所有实现都能定义接口ID,但是在ERC721的情况下,它有更大的可能性,因为社区同意从一开始就应用ERC165。 如果以下查询的返回值为true,则表示您具有合规合同,否则只需还原该事务。

// you can call this in your contracts
IERC721(contractAddress).supportsInterface(0x80ac58cd)

此外,用于手动检查的有用资源bytes4给定方法的是4byte.directory

如果您要询问链外,请使用以下功能:

getContract(url, smartContractAddress){
    const Web3Eth = require('web3-eth');

    const abi_ = this.getABI();
    const web3Eth = new Web3Eth(Web3Eth.givenProvider || url);
    return new web3Eth.Contract(abi_, smartContractAddress);
}

async getERCtype(contract){
    const is721 = await contract.methods.supportsInterface('0x80ac58cd').call();
    if(is721){
        return "ERC721";
    }
    const is1155 = await contract.methods.supportsInterface('0xd9b67a26').call();
    if(is1155){
        return "ERC1155";
    }
    return undefined;
}

getABI(){
    return [         
        {"constant":true,"inputs": [
                {"internalType":"bytes4","name": "","type": "bytes4"}],
            "name": "supportsInterface",
            "outputs": [{"internalType":"bool","name": "","type": "bool"}],
            "payable": false,"stateMutability":"view","type": "function"}         
    ];
}

像这样:

const contract = getContract(url, smartContractAddress);
const type = await getERCtype(contract);
console.log(type);

我对所提供的答案感到惊讶。 (我要么对以太坊一无所知,要么根本不懂英语)

问题指出,给定以太坊地址,这是否是以太坊合约地址?

首先,你必须确定这个地址是合约地址还是外部拥有的账户地址。 如何确定以太坊地址是否为合约

如果是合约地址,那么你只能获取存储在区块链中的字节码。 现在你必须对字节码进行逆向工程才能获得合约功能,但这几乎是不可能的。 有一些反编译器,但它们并不能完美地从字节码创建合约代码。

ERC165只是检查当前合约签名是否支持给定的 interfaceId。 由于您只有以太坊地址,因此这对这个问题没有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM