How to get signature by JS with contract use ECDSA verify

I have code solidity . Function message hash:

    function _hash(
        uint256 _cid,
        IStarNFT _starNFT,
        uint256 _dummyId,
        uint256 _powah,
        address _account
    ) public view returns (bytes32) {
        return
        _hashTypedDataV4(
            keccak256(
                abi.encode(
                    keccak256(
                        "NFT(uint256 cid,address starNFT,uint256 dummyId,uint256 powah,address account)"
                    ),
                    _cid,
                    _starNFT,
                    _dummyId,
                    _powah,
                    _account
                )
            )
        );
    }

I want to use JS to get signature with data:
_cid: 123
_starNFT: 0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97
_dummyId: 222
_powah: 345
_account : 0x26c1df84f7917c5d90f1d8d744b0caaf1ae3fa11

1 Like

First of all, if you're attempting to calculate the selector of this function:

function NFT(uint256 cid,address starNFT,uint256 dummyId,uint256 powah,address account)

Then your code is wrong for several different reasons:

First, instead of this:

"NFT(uint256 cid,address starNFT,uint256 dummyId,uint256 powah,address account)"

You should be using this:

"NFT(uint256,address,uint256,uint256,address)"

Second, instead of this:

keccak256(...)

You should be using this:

bytes4(keccak256(...))

Third, instead of this:

abi.encode(...)

You should be using this:

abi.encodeWithSelector(...))

So in short, you need to do something like:

abi.encodeWithSelector(
    bytes4(keccak256(
        "NFT(uint256,addres,uint256,uint256,addres)"
    )),
    _cid,
    _starNFT,
    _dummyId,
    _powah,
    _account
)

Second, without taking all of the above into account, in order to emulate all of that in JS, you can do:

const Web3 = require("web3");

const _cid = Web3.utils.toBN(123).toString(16, 256 / 4);
const _starNFT ="0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97";
const _dummyId = Web3.utils.toBN(222).toString(16, 256 / 4);
const _powah = Web3.utils.toBN(345).toString(16, 256 / 4);
const _account = "0x26c1df84f7917c5d90f1d8d744b0caaf1ae3fa11";
const _func_sig = "NFT(uint256 cid,address starNFT,uint256 dummyId,uint256 powah,address account)";

const result = Web3.utils.keccak256("0x"
    + Web3.utils.keccak256(_func_sig)
    + _cid
    + _starNFT
    + _dummyId
    + _powah
    + _account
);

console.log(result);

Again - note that the second part in this answer doesn't take into account all of the potential issues raised in the first part of this answer, as it is not really clear what you're trying to achieve here.


If it is indeed a function-call which you are trying to encode, then you can do something like:

const result = new Web3().eth.abi.encodeFunctionCall(
    {
        name: "NFT",
        type: "function",
        inputs: [
            {type: "uint256", name: "cid"},
            {type: "address", name: "starNFT"},
            {type: "uint256", name: "dummyId"},
            {type: "uint256", name: "powah"},
            {type: "address", name: "account"},
        ]
    },
    [
        "123",
        "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97",
        "222",
        "345",
        "0x26c1df84f7917c5d90f1d8d744b0caaf1ae3fa11",
    ]
);

console.log(result);
2 Likes