错误:无法解码结果数据(value =“0x”,info = {“method”:“getCreatorCount”,“signature”:“getCreatorCount()”},code = BAD_DATA,version = 6.6.2)

问题描述 投票:0回答:4

我正在使用 Solidity 和 Hardhat 来创建智能合约。版本 6.6.2。这是我的智能合约的样子:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract CreatorRegistry {
    struct Creator {
        address walletAddress;
        string name;
        string b64Image;
    }

    Creator[] public creators;
    mapping(address => bool) public isCreatorRegistered;

    function signup(address _walletAddress, string memory _name, string memory _b64Image) public {
        require(!isCreatorRegistered[_walletAddress], "Address is already registered");

        Creator memory newCreator;
        newCreator.walletAddress = _walletAddress;
        newCreator.name = _name;
        newCreator.b64Image = _b64Image;

        creators.push(newCreator);
        isCreatorRegistered[_walletAddress] = true;
    }

    function getCreator(uint256 _index) public view returns (
        address walletAddress,
        string memory name,
        string memory b64Image
    ) {
        require(_index < creators.length, "Invalid index");

        Creator storage creator = creators[_index];
        walletAddress = creator.walletAddress;
        name = creator.name;
        b64Image = creator.b64Image;
    }

    function getCreatorCount() public view returns (uint256) {
        return creators.length;
    }
}

这是我尝试调用合约的方式:

// javascript frontend
const newUser =
                            (await registrationContract?.getCreatorCount?.()) ??
                            'Oops we lost';
                        console.log('New User = ', newUser);

但是失败并出现错误:

Error: could not decode result data (value="0x", info={ "method": "getCreatorCount", "signature": "getCreatorCount()" }, code=BAD_DATA, version=6.6.2)

有人可以帮助我了解这里出了什么问题吗?

从错误来看,它似乎无法解码 javascript 端的数据,或者这是 Solidity 端的问题?我该如何解决这个问题?

编辑1:

正如 @Yilmaz 在评论中提到的:

?.
是 javascript 中的可选链接运算符,可确保在属性未定义时不会使程序崩溃。不过,为了确保万无一失,我也这样做了:

const newUserCount =
                            (await registrationContract.getCreatorCount()) ??
                            'Oops we lost';

也失败了。

编辑2 Github 论坛:有一个 github 论坛表明由于网络不同,可能会出现此问题:https://github.com/web3/web3.js/issues/1629

所以我确保我指的是本地主机网络和正确的钱包地址。即使在配置之后,我仍然收到相同的错误:

这就是我的注册合同的样子:

'use client';
import { Contract, InterfaceAbi, ethers } from 'ethers';
import Web3Modal from 'web3modal';
import { ContractRunner } from 'ethers';
import {
    contentCreatorABI,
    creatorRegistryABI,
    contentCreatorAddress,
    creatorRegistryAddress,
} from './contractClient';
import { Web3Window } from './web3SignIn';

const getSmartContract = (
    address: string,
    abi: InterfaceAbi,
    provider: ContractRunner
): Contract => new ethers.Contract(address, abi, provider);

const getContracts = async (): Promise<{
    error: boolean;
    message?: string;
    data?: { creatorContract?: Contract; registrationContract: Contract };
}> => {
    const { ethereum } = window as Web3Window;
    if (!ethereum)
        return {
            error: true,
            message: 'Please install metamask extension and try refreshing the page',
        };
    try {
        const provider = new ethers.BrowserProvider(ethereum);
        const signer = await provider.getSigner();
        const creatorContract = getSmartContract(
            contentCreatorAddress,
            contentCreatorABI,
            signer
        );
        const registrationContract = getSmartContract(
            creatorRegistryAddress,
            creatorRegistryABI,
            signer
        );

        return { error: false, data: { registrationContract } };
    } catch (err) {
        return { error: true, message: (err as { message: string }).message };
    }
};

export { getContracts };
solidity smartcontracts decentralized-applications
4个回答
3
投票

我遇到了类似的情况,并在将智能合约部署到本地网络后设法解决了这个问题:npx Hardhat run scripts/deploy.ts --network localhost

您可以使用 Hardhat 配置中的任何网络作为目标: npx Hardhat run --network < your-network >scripts/deploy.js


1
投票

对我来说,错误出现是因为我在

uint8
中得到了solidity的响应,这相当于javascript中的long,并且需要正确解密。

正确解密后,问题就解决了。

这是最终代码:

在客户端:

'use client';
import { Contract, InterfaceAbi, ethers } from 'ethers';
import { ContractRunner } from 'ethers';
import {
    contentCreatorABI,
    creatorRegistryABI,
    contentCreatorAddress,
    creatorRegistryAddress,
} from './contractClient';
import { Web3Window } from './web3SignIn';

const getSmartContract = (
    address: string,
    abi: InterfaceAbi,
    provider: ContractRunner
): Contract => new ethers.Contract(address, abi, provider);

const getContracts = async (): Promise<{
    error: boolean;
    message?: string;
    data?: { creatorContract: Contract; registrationContract: Contract };
}> => {
    const { ethereum } = window as Web3Window;
    if (!ethereum)
        return {
            error: true,
            message: 'Please install metamask extension and try refreshing the page',
        };
    try {
        const provider = new ethers.BrowserProvider(ethereum);
        const signer = await provider.getSigner();
        const creatorContract = getSmartContract(
            contentCreatorAddress,
            contentCreatorABI,
            signer
        );
        const registrationContract = getSmartContract(
            creatorRegistryAddress,
            creatorRegistryABI,
            signer
        );

        return { error: false, data: { registrationContract, creatorContract } };
    } catch (err) {
        return { error: true, message: (err as { message: string }).message };
    }
};

export { getContracts };

这是我调用它的方法:

'use client';
import { loginWithWallet } from '@@/solidity/web3SignIn';
import useWeb3Store from '@@/store/web3Walltet';
import classes from './MetaMaskLogin.module.css';
import { useEffect, useState } from 'react';
import { getContracts } from '@@/solidity/contracts';
import { useRouter } from 'next/navigation';
import { NormalImage } from '@@/components/NormalImage';

const MetaMaskLogin = () => {
    const {
        setAccount,
        setNameAndImg,
        setCreatorContract,
        setRegistrationContract,
        registrationContract,
        account,
    } = useWeb3Store();
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [firstTime, setFirstTime] = useState(false);
    const [uName, setUName] = useState('');
    const [imgUrl, setImgUrl] = useState(
        'https://www.gravatar.com/avatar/00000000000000000000000000000000'
    );

    const router = useRouter();

    const loginToMetaMask = async () => {
        setLoading(true);
        loginWithWallet()
            .then((account) => {
                if (account) {
                    setAccount(account);
                } else
                    setError(
                        'Unexpected error occured while logging in. Please refresh the page and retry.'
                    );
            })
            .catch((error) => {
                setError(`Error occured while logging in: ${error.message}`);
            })
            .finally(() => setLoading(false));
    };

    const getUserDetails = async () => {
        if (registrationContract)
            try {
                const newUserCount =
                    (await registrationContract.getCreatorByAddress(account)) ??
                    'Oops we lost';
                const [_, name, b64Image] = newUserCount;
                if (name === 'Not Found') setFirstTime(true);
                else {
                    setFirstTime(false);
                    setNameAndImg(name, b64Image);
                    //TODO: Redirect to main page
                    router.push('/');
                }
            } catch (err) {
                console.log('Error occured with smart contract = ', err);
            }
    };

    useEffect(() => {
        if (account) {
            setLoading(true);
            getContracts()
                .then(async ({ error, data, message }) => {
                    if (!error && data) {
                        const { creatorContract, registrationContract } = data;
                        setCreatorContract(creatorContract);
                        setRegistrationContract(registrationContract);
                    } else
                        setError(
                            `Error occured while fetching smart contracts: ${
                                message ?? 'Unknown error'
                            }`
                        );
                })
                .catch((error) => setError(error.message))
                .finally(() => setLoading(false));
        }
    }, [account, setCreatorContract, setRegistrationContract]);

    useEffect(() => {
        getUserDetails();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [registrationContract]);

    const registerUser = async () => {
        setLoading(true);
        if (registrationContract) {
            const user = await registrationContract.signup(account, uName, imgUrl);
            await user.wait();
            setFirstTime(false);
            //TODO: Redirect to main page
            setLoading(false);
            router.push('/');
        }
    };

    return (
        <div className={classes.container}>
            <NormalImage
                className={classes.metamaskLogo}
                src='/meta-mask.png'
            />
            {loading ? (
                <p className={classes.SignInText}>Loading...</p>
            ) : (
                <button
                    className={'StandardButton'}
                    onClick={loginToMetaMask}
                >
                    Login to Metamask
                </button>
            )}
            {error != null && <p className={classes.ErrorText}>{error}</p>}
            {firstTime && (
                <>
                    <input
                        type='text'
                        className={classes.Input}
                        placeholder='Please Input your Name'
                        value={uName}
                        onChange={(e) => setUName(e.target.value)}
                    />
                    <input
                        type='url'
                        className={classes.Input}
                        placeholder='Please Input your Image Avatar URL'
                        value={imgUrl}
                        onChange={(e) => setImgUrl(e.target.value)}
                    />
                    <button
                        className='StandardButton'
                        onClick={registerUser}
                    >
                        Complete Registration
                    </button>
                </>
            )}
        </div>
    );
};

export default MetaMaskLogin;

在服务器端:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract CreatorRegistry {
    struct Creator {
        address walletAddress;
        string name;
        string b64Image;
    }

    Creator[] public creators;
    mapping(address => bool) public isCreatorRegistered;

    function signup(address _walletAddress, string memory _name, string memory _b64Image) public {
        require(!isCreatorRegistered[_walletAddress], "Address is already registered");

        Creator memory newCreator;
        newCreator.walletAddress = _walletAddress;
        newCreator.name = _name;
        newCreator.b64Image = _b64Image;

        creators.push(newCreator);
        isCreatorRegistered[_walletAddress] = true;
    }

    function getCreator(uint256 _index) public view returns (
        address walletAddress,
        string memory name,
        string memory b64Image
    ) {
        require(_index < creators.length, "Invalid index");

        Creator storage creator = creators[_index];
        walletAddress = creator.walletAddress;
        name = creator.name;
        b64Image = creator.b64Image;
    }

    function getCreatorCount() public view returns (uint256) {
        return creators.length;
    }

    function getCreatorByAddress(address _walletAddress) public view returns (
        address walletAddress,
        string memory name,
        string memory b64Image
    ) {
        for (uint256 i = 0; i < creators.length; i++) {
            Creator storage creator = creators[i];
            if (creator.walletAddress == _walletAddress) {
                walletAddress = creator.walletAddress;
                name = creator.name;
                b64Image = creator.b64Image;
                return (walletAddress, name, b64Image);
            }
        }

        // Creator not found
        return(walletAddress, "Not Found", "Not Found");
    }
}

0
投票

我的问题是我没有运行 npm install 并在项目中安装依赖项。


0
投票

我的问题解决得很简单,当调用一个应该返回所有者地址的函数时,我收到一个错误:

错误:无法解码结果数据(value =“0x”,info = {“method”:“callme”,“signature”:“callme()”},code = BAD_DATA,version = 6.9.0)

function callme() external view returns (address) {
    return msg.sender;
}

通过从函数中删除

view
关键字,一切正常,但在这种情况下,solidity 编译器会发出警告。

所以,我的答案是:

function callme() external returns (address) {
    return msg.sender;
}
© www.soinside.com 2019 - 2024. All rights reserved.