7

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

4

3 回答 3

3

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,但考虑到社区从一开始就同意应用 ERC165 的事实,它在 ERC721 的情况下工作的可能性更高。如果下面查询的返回值为真,那么说明你有一个合规的合约,否则就恢复交易。

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

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

于 2018-11-17T15:28:06.857 回答
2

有许多可能的方法来实现这一点。一种可能的快速而肮脏的解决方案是通过调用以下命令来检查合约地址上是否存在 ERC20 函数:

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

非 ERC20 将返回 'null'0x十六进制响应,而 ERC20 将为您提供 32byte uint,在本例中为 0 但如果您在数据中提供地址,那么它将为您提供该地址的实际代币余额。

这不是确定合约是 ERC20 的保证方法,因为其他合约可能会暴露相同的功能,但它是一种快速简便的检查。您可以添加额外的电话totalSupply()等以获得更多确认。

于 2017-07-31T14:31:43.983 回答
2

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

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);
于 2021-07-08T02:31:50.420 回答