如何检测以太坊地址是否是ERC20令牌合同?

时间:2017-07-28 03:06:01

标签: ethereum solidity erc20

如果我只从输入中获得以太坊地址,有没有办法找出它是否符合ERC20令牌标准?

3 个答案:

答案 0 :(得分:1)

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

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

非ERC20将返回' null' 0x十六进制响应,而ERC20将为您提供32字节uint,在这种情况下为0,但如果您在数据中提供地址,那么它将为您提供该地址的实际令牌余额。

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

答案 1 :(得分:0)

ERC165解决了这个问题,但是不幸的是,大多数ERC20实现都不支持它(截至2018年11月,至少是OpenZeppelin doesn't)。这意味着您可以尝试调用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,但鉴于社区同意从一开始就直接应用ERC165,因此在ERC721情况下它更有可能工作。如果以下查询的返回值为true,则表示您已遵守合同,否则只需还原交易即可。

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

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

答案 2 :(得分:0)

如果您询问的是链下问题,请使用以下功能:

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);