0

I am facing a problem where recoveredAddress is not restored correctly. We assume that the address of the owner who originally deployed the smart contract is returned. Am I making some big mistake? Can someone please let me know? Thank you.

  • "@nomicfoundation/hardhat-toolbox": "^3.0.0"
  • "hardhat": "^2.17.3",

contracts/VerifyToken.sol

pragma solidity ^0.8.21;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "hardhat/console.sol";

contract VerifyToken {
    using ECDSA for bytes32;

    address public signer;

    constructor() {
        signer = msg.sender;
    }

    function verify(bytes memory signature) public view returns (bool) {
        bytes32 messageHash = keccak256(abi.encodePacked(msg.sender));
        bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash();
        address recoveredSigner = ethSignedMessageHash.recover(signature);

        console.log("signer: %s", signer);
        console.log("recoveredSigner: %s", recoveredSigner);

        bool isValid = recoveredSigner == signer;

        return isValid;
    }
}

/test/VerifyToken.ts

import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
import { expect } from "chai";
import { ethers } from "hardhat";

describe("VerifyToken", function () {
  async function deployVerifyTokenFixture() {
    const [owner, addr1] = await ethers.getSigners();
    const verifyToken = await ethers.deployContract("VerifyToken");
    await verifyToken.waitForDeployment();
    return { verifyToken, owner, addr1 };
  }

  describe("Verifying", function () {
    it("Should 1", async function () {
      const { verifyToken, owner } = await loadFixture(
        deployVerifyTokenFixture
      );

      const messageHash = ethers.keccak256(
        new ethers.AbiCoder().encode(["address"], [owner.address])
      );
      const signature = await owner.signMessage(ethers.toBeArray(messageHash));

      const isValid = await verifyToken.verify(signature);
      expect(isValid).to.equal(true);
    });

    it("Should 2", async function () {
      const { verifyToken, addr1 } = await loadFixture(
        deployVerifyTokenFixture
      );

      const messageHash = ethers.keccak256(
        new ethers.AbiCoder().encode(["address"], [addr1.address])
      );
      const signature = await addr1.signMessage(ethers.toBeArray(messageHash));

      const isValid = await verifyToken.verify(signature);
      expect(isValid).to.equal(false);
    });
  });
});
2
  • Most likely some minor error somewhere in code. Difficult to track down. Sep 27 at 8:54
  • I'm sorry. There was a mistake in the code and it has been corrected.
    – tgf8faf
    Sep 28 at 10:35

1 Answer 1

1

abiCoder.encode is not packed, eg.:

abiCoder.encode(["address"], ['0x473173aDa23BE87a4740646b09F9c22d115CE5a0'])
'0x000000000000000000000000473173ada23be87a4740646b09f9c22d115ce5a0'

but in solidity you used abi.encodePacked instead of abi.encode:

abi.encodePacked(address(0x473173aDa23BE87a4740646b09F9c22d115CE5a0))
hex"473173ada23be87a4740646b09f9c22d115ce5a0"
1
  • Oh! That was very helpful. Thank you very much! I confirmed that it works fine with abi.encode.
    – tgf8faf
    Sep 28 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.